🌳
pt0/deployF/k8sProvF/k3sF/setupK3sIngressNginxAI.mts
10import * as _ from 'lodash-es'
13export const k8sK3sIngress = async ({ingressNginxVersion}: {ingressNginxVersion: string}) => {
14 const { cluster_name, serverIp } = getKlusterCtx()
15 const action = getAction()
17 if (action !== 'apply') {
18 console.log('skipping ingress-nginx setup for action:', action)
19 return
20 }
22 assertDefined(serverIp, {cluster_name})
24 const kubeConfigPath = getKubeConfigPath(cluster_name)
25 const wcCertName = get1WcCertName()
27 const nodePorts = await applyIngressNginxBaremetal({version: ingressNginxVersion, kubeConfigPath})
29 // Patch ingress-nginx controller with both publish-status-address and default-ssl-certificate
30 await patchIngressController({cluster_name, serverIp, wcCertName})
31 await patchIngressCacheConfig({cluster_name})
33 console.log('ingress-nginx installed for k3s')
34 return {nodePorts, serverIp}
37const patchIngressController = async ({cluster_name, serverIp, wcCertName}: {cluster_name: string, serverIp: string, wcCertName: string}) => {
38 const resource: any = await read2Resource({
39 cluster_name,
40 resource: {
41 apiVersion: 'apps/v1',
42 kind: 'Deployment',
43 metadata: { name: 'ingress-nginx-controller', namespace: 'ingress-nginx' },
44 }
45 })
47 assertDefined(resource, {cluster_name})
49 const podSpec = resource.spec.template.spec
50 const container = podSpec.containers[0]
51 const publishStatusArg = `--publish-status-address=${serverIp}`
52 const defaultSslArg = `--default-ssl-certificate=default/${wcCertName}`
54 let changed = false
56 // Enable hostNetwork so ingress-nginx binds to ports 80/443 directly
57 if (!podSpec.hostNetwork) {
58 podSpec.hostNetwork = true
59 podSpec.dnsPolicy = 'ClusterFirstWithHostNet'
60 console.log('enabling hostNetwork mode')
61 changed = true
62 }
64 // Add/update --publish-status-address
65 const publishI = _.findIndex(container.args, (argS: string) => _.startsWith(argS, '--publish-status-address'))
66 if (publishI === -1) {
67 container.args.push(publishStatusArg)
68 console.log(`adding ${publishStatusArg}`)
69 changed = true
70 } else if (container.args[publishI] !== publishStatusArg) {
71 container.args[publishI] = publishStatusArg
72 console.log(`updating to ${publishStatusArg}`)
73 changed = true
74 }
76 // Add/update --default-ssl-certificate
77 const sslI = _.findIndex(container.args, (argS: string) => _.startsWith(argS, '--default-ssl-certificate'))
78 if (sslI === -1) {
79 container.args.push(defaultSslArg)
80 console.log(`adding ${defaultSslArg}`)
81 changed = true
82 } else if (container.args[sslI] !== defaultSslArg) {
83 container.args[sslI] = defaultSslArg
84 console.log(`updating to ${defaultSslArg}`)
85 changed = true
86 }
88 if (!changed) {
89 console.log('ingress-nginx controller already configured')
90 return
91 }
93 await res1Action({ action: 'apply', resource: resource as KubeResource, cluster_name })
96const ingressCacheHttpSnippet = 'proxy_cache_path /tmp/nginx-cache levels=1:2 keys_zone=nginx-cache:10m max_size=500m inactive=60m use_temp_path=off;'
98const patchIngressCacheConfig = async ({cluster_name}: {cluster_name: string}) => {
99 const cm: any = await read2Resource({
100 cluster_name,
101 resource: {
102 apiVersion: 'v1',
103 kind: 'ConfigMap',
104 metadata: { name: 'ingress-nginx-controller', namespace: 'ingress-nginx' },
105 }
106 })
107 assertDefined(cm, {cluster_name})
109 const checksum = calcHash(ingressCacheHttpSnippet + '|true|Critical')
110 const cmReady = cm.data?.['http-snippet']?.includes('nginx-cache') && cm.data?.['allow-snippet-annotations'] === 'true'
112 const deploy: any = await read2Resource({
113 cluster_name,
114 resource: {
115 apiVersion: 'apps/v1',
116 kind: 'Deployment',
117 metadata: { name: 'ingress-nginx-controller', namespace: 'ingress-nginx' },
118 }
119 })
120 assertDefined(deploy, {cluster_name})
121 deploy.spec.template.metadata.annotations = deploy.spec.template.metadata.annotations || {}
122 const currentChecksum = deploy.spec.template.metadata.annotations['checksum/config']
124 if (cmReady && currentChecksum === checksum) return
126 if (!cmReady) {
127 cm.data = cm.data || {}
128 cm.data['http-snippet'] = ingressCacheHttpSnippet
129 cm.data['allow-snippet-annotations'] = 'true'
130 cm.data['annotation-risk-level'] = 'Critical'
131 console.log('patching ingress-nginx ConfigMap with proxy_cache_path + snippet annotations')
132 await res1Action({ action: 'apply', resource: cm as KubeResource, cluster_name })
133 }
135 deploy.spec.template.metadata.annotations['checksum/config'] = checksum
136 console.log('restarting ingress-nginx controller to pick up ConfigMap changes')
137 await res1Action({ action: 'apply', resource: deploy as KubeResource, cluster_name })
139 const webhook: any = await read2Resource({
140 cluster_name,
141 resource: {
142 apiVersion: 'admissionregistration.k8s.io/v1',
143 kind: 'ValidatingWebhookConfiguration',
144 metadata: { name: 'ingress-nginx-admission' },
145 }
146 })
147 if (webhook) {
148 console.log('removing ingress-nginx admission webhook (blocks configuration-snippet annotations)')
149 await res1Action({ action: 'delete', resource: webhook as KubeResource, cluster_name })
150 }