Skip to content

Commit bbfb5a9

Browse files
iQQBotroboquat
authored andcommitted
make vm support ssh gateway
1 parent c691df8 commit bbfb5a9

File tree

4 files changed

+169
-2
lines changed

4 files changed

+169
-2
lines changed

.werft/jobs/build/deploy-to-preview-environment.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,11 @@ async function deployToDevWithInstaller(werft: Werft, jobConfig: JobConfig, depl
317317
await waitUntilAllPodsAreReady(deploymentConfig.namespace, installer.options.kubeconfigPath, { slice: installerSlices.DEPLOYMENT_WAITING })
318318
werft.done(installerSlices.DEPLOYMENT_WAITING);
319319

320-
await addDNSRecord(werft, deploymentConfig.namespace, deploymentConfig.domain, !withVM, installer.options.kubeconfigPath)
320+
if (!withVM) {
321+
await addDNSRecord(werft, deploymentConfig.namespace, deploymentConfig.domain, !withVM, installer.options.kubeconfigPath)
322+
} else {
323+
await addVMDNSRecord(werft, destname, domain)
324+
}
321325
addAgentSmithToken(werft, deploymentConfig.namespace, installer.options.kubeconfigPath, tokenHash)
322326

323327
// TODO: Fix sweeper, it does not appear to be doing clean-up
@@ -676,6 +680,35 @@ async function addDNSRecord(werft: Werft, namespace: string, domain: string, isL
676680
werft.done(installerSlices.DNS_ADD_RECORD);
677681
}
678682

683+
async function addVMDNSRecord(werft: Werft, name: string, domain: string) {
684+
const ingressIP = getHarvesterIngressIP()
685+
let proxyLBIP = null
686+
werft.log(installerSlices.DNS_ADD_RECORD, "Getting loadbalancer IP");
687+
for (let i = 0; i < 60; i++) {
688+
try {
689+
let lb = exec(`kubectl --kubeconfig ${CORE_DEV_KUBECONFIG_PATH} -n loadbalancers get service lb-${name} -o=jsonpath='{.status.loadBalancer.ingress[0].ip}'`, { silent: true })
690+
if (lb.length > 4) {
691+
proxyLBIP = lb.toString()
692+
break
693+
}
694+
await sleep(1000)
695+
} catch (err) {
696+
await sleep(1000)
697+
}
698+
}
699+
if (proxyLBIP == null) {
700+
werft.fail(installerSlices.DNS_ADD_RECORD, new Error("Can't get loadbalancer IP"));
701+
}
702+
werft.log(installerSlices.DNS_ADD_RECORD, "Get loadbalancer IP: " + proxyLBIP);
703+
704+
await Promise.all([
705+
createDNSRecord(domain, 'preview-gitpod-dev-com', ingressIP, installerSlices.DNS_ADD_RECORD),
706+
createDNSRecord(`*.${domain}`, 'preview-gitpod-dev-com', ingressIP, installerSlices.DNS_ADD_RECORD),
707+
createDNSRecord(`*.ws.${domain}`, 'preview-gitpod-dev-com', proxyLBIP, installerSlices.DNS_ADD_RECORD),
708+
])
709+
werft.done(installerSlices.DNS_ADD_RECORD);
710+
}
711+
679712
export async function issueMetaCerts(werft: Werft, certName: string, certsNamespace: string, domain: string, withVM: boolean, slice: string) {
680713
const additionalSubdomains: string[] = ["", "*.", `*.ws${withVM ? '' : '-dev'}.`]
681714
var metaClusterCertParams = new IssueCertificateParams();
@@ -720,6 +753,11 @@ function getCoreDevIngressIP(): string {
720753
return "104.199.27.246";
721754
}
722755

756+
// returns the static IP address
757+
function getHarvesterIngressIP(): string {
758+
return "159.69.172.117";
759+
}
760+
723761
function metaEnv(_parent?: ExecOptions): ExecOptions {
724762
return env("", _parent);
725763
}

.werft/jobs/build/prepare.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import * as VM from '../../vm/vm'
55
import { CORE_DEV_KUBECONFIG_PATH, GCLOUD_SERVICE_ACCOUNT_PATH, HARVESTER_KUBECONFIG_PATH } from "./const";
66
import { issueMetaCerts } from './deploy-to-preview-environment';
77
import { JobConfig } from './job-config';
8+
import * as Manifests from '../../vm/manifests';
9+
import { sleep } from '../../util/util';
810

911
const phaseName = "prepare";
1012
const prepareSlices = {
@@ -86,6 +88,7 @@ function decideHarvesterVMCreation(werft: Werft, config: JobConfig) {
8688
} else {
8789
werft.currentPhaseSpan.setAttribute("werft.harvester.created_vm", false)
8890
}
91+
applyLoadBalancer({ name: config.previewEnvironment.destname })
8992
werft.done(prepareSlices.BOOT_VM)
9093
}
9194

@@ -108,3 +111,30 @@ function createVM(werft: Werft, config: JobConfig) {
108111
VM.startVM({ name: config.previewEnvironment.destname })
109112
werft.currentPhaseSpan.setAttribute("werft.harvester.created_vm", true)
110113
}
114+
115+
function applyLoadBalancer(option: { name: string }) {
116+
const namespace = `preview-${option.name}`;
117+
function kubectlApplyManifest(manifest: string, options?: { validate?: boolean }) {
118+
exec(`
119+
cat <<EOF | kubectl --kubeconfig ${CORE_DEV_KUBECONFIG_PATH} apply --validate=${!!options?.validate} -f -
120+
${manifest}
121+
EOF
122+
`);
123+
}
124+
function getVMServiceIP() {
125+
let ip = exec(
126+
`kubectl --kubeconfig ${HARVESTER_KUBECONFIG_PATH} -n ${namespace} get service proxy -o=jsonpath='{.spec.clusterIP}'`,
127+
{ silent: true },
128+
);
129+
if (ip.length > 4) {
130+
return ip;
131+
}
132+
return null;
133+
}
134+
let forwardIP = getVMServiceIP();
135+
if (forwardIP == null) {
136+
throw new Error("Failed to get VM IP");
137+
}
138+
kubectlApplyManifest(Manifests.LBDeployManifest({ name: option.name, destIP: forwardIP }));
139+
kubectlApplyManifest(Manifests.LBServiceManifest({ name: option.name }));
140+
}

.werft/util/gcloud.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ function getExternalIp(name: string, region = "europe-west1") {
3939
export async function createDNSRecord(domain: string, dnsZone: string, IP: string, slice: string): Promise<void> {
4040
const werft = getGlobalWerftInstance()
4141

42-
const dnsClient = new DNS({ projectId: 'gitpod-dev', keyFilename: GCLOUD_SERVICE_ACCOUNT_PATH })
42+
const dnsClient = new DNS({
43+
projectId: dnsZone === "gitpod-dev.com" ? "gitpod-dev" : "gitpod-core-dev",
44+
keyFilename: GCLOUD_SERVICE_ACCOUNT_PATH,
45+
});
4346
const zone = dnsClient.zone(dnsZone)
4447

4548
if (!(await matchesExistingRecord(zone, domain, IP))) {

.werft/vm/manifests.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,102 @@ spec:
140140
`
141141
}
142142

143+
type LBServiceManifestOptions = {
144+
name: string
145+
}
146+
147+
export function LBServiceManifest({ name }: LBServiceManifestOptions) {
148+
return `
149+
apiVersion: v1
150+
kind: Service
151+
metadata:
152+
name: lb-${name}
153+
namespace: loadbalancers
154+
spec:
155+
ports:
156+
- name: ssh-gateway
157+
protocol: TCP
158+
port: 22
159+
targetPort: 22
160+
- name: https
161+
protocol: TCP
162+
port: 443
163+
targetPort: 443
164+
selector:
165+
gitpod.io/lbName: ${name}
166+
type: LoadBalancer
167+
`
168+
}
169+
170+
type LBDeployManifestOptions = {
171+
name: string
172+
destIP: string
173+
}
174+
175+
export function LBDeployManifest({ name, destIP }: LBDeployManifestOptions) {
176+
return `
177+
apiVersion: apps/v1
178+
kind: Deployment
179+
metadata:
180+
name: lb-${name}
181+
namespace: loadbalancers
182+
labels:
183+
gitpod.io/lbName: ${name}
184+
spec:
185+
replicas: 1
186+
selector:
187+
matchLabels:
188+
gitpod.io/lbName: ${name}
189+
template:
190+
metadata:
191+
name: lb
192+
labels:
193+
gitpod.io/lbName: ${name}
194+
spec:
195+
containers:
196+
- name: lb-port-22
197+
image: rancher/klipper-lb:v0.3.4
198+
ports:
199+
- name: lb-port-22
200+
containerPort: 22
201+
protocol: TCP
202+
env:
203+
- name: SRC_PORT
204+
value: '22'
205+
- name: DEST_PROTO
206+
value: TCP
207+
- name: DEST_PORT
208+
value: '22'
209+
- name: DEST_IPS
210+
value: ${destIP}
211+
securityContext:
212+
capabilities:
213+
add:
214+
- NET_ADMIN
215+
- name: lb-port-443
216+
image: rancher/klipper-lb:v0.3.4
217+
ports:
218+
- name: lb-port-443
219+
containerPort: 443
220+
protocol: TCP
221+
env:
222+
- name: SRC_PORT
223+
value: '443'
224+
- name: DEST_PROTO
225+
value: TCP
226+
- name: DEST_PORT
227+
value: '443'
228+
- name: DEST_IPS
229+
value: ${destIP}
230+
securityContext:
231+
capabilities:
232+
add:
233+
- NET_ADMIN
234+
serviceAccount: proxy
235+
enableServiceLinks: false
236+
`
237+
}
238+
143239
type UserDataSecretManifestOptions = {
144240
vmName: string
145241
namespace: string,

0 commit comments

Comments
 (0)