Kong和Konga在K8s部署真的很難嗎?
本文轉載自微信公眾號「運維開發故事」,作者小姜。轉載本文請聯系運維開發故事公眾號。
背景
隨著k8s的成熟,在k8s上使用ingress-nginx、traefik、apisix等各類ingress的人也越來越多。ingress-kong也可以作為k8s的ingress使用,當然kong也可以單獨作為微服務的gateway網關來使用。
如果kong是作為ingress來使用,那么需要使用kong鏡像來部署一個ingress-kong和一個kong/kubernetes-ingress-controller鏡像來部署一個kong的ingress-controller。還需要部署sa賬號和rbac,還有CRD資源。
如果kong只是作為一個gateway來替換springcloud中的gateway來使用,那么只需要部署sa賬號和rbac,然后用kong鏡像部署一個pod即可當做gateway使用,crd也就不需要了。
kong和konga支持MySQL、MongoDB、PostgresSQL三種數據庫。而我這里選擇的是PostgresSQL。因為公司都是all in docker,all in kubernetes,因此這里也就選擇了在k8s中部署kong和konga。下面記錄了一下部署kong和konga過程中遇到的一些報錯和排查解決方案思路手段。
部署konga
- $ cat kong-ui-pre.yaml
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- labels:
- appName: konga-ui-aggre-sit
- appEnv: sit
- name: konga-ui-aggre-sit
- namespace: kong
- spec:
- replicas: 1
- selector:
- matchLabels:
- appName: konga-ui-aggre-sit
- appEnv: sit
- template:
- metadata:
- labels:
- appName: konga-ui-aggre-sit
- appEnv: sit
- spec:
- imagePullSecrets:
- - name: registry-auth
- containers:
- - env:
- - name: NODE_ENV
- value: "production"
- - name: DB_ADAPTER
- value: "postgres"
- - name: DB_HOST
- value: "你自己的pgsql地址"
- - name: DB_PORT
- value: "你自己的pgsql端口"
- - name: DB_USER
- value: "kong"
- - name: DB_PASSWORD
- value: "你自己的pgsql密碼"
- - name: DB_DATABASE
- value: "konga"
- - name: TOKEN_SECRET
- value: "自己生成隨機字符串"
- - name: NO_AUTH
- value: "false"
- - name: NODE_TLS_REJECT_UNAUTHORIZED
- value: "0"
- image: registry.ayunw.cn/kube-system/pantsel/konga:0.14.9
- imagePullPolicy: IfNotPresent
- livenessProbe:
- failureThreshold: 3
- httpGet:
- path: /
- port: 1337
- scheme: HTTP
- initialDelaySeconds: 5
- periodSeconds: 10
- successThreshold: 1
- timeoutSeconds: 1
- name: konga-ui-aggre-sit
- ports:
- - containerPort: 1337
- name: kong-ui
- protocol: TCP
- readinessProbe:
- failureThreshold: 3
- httpGet:
- path: /
- port: 1337
- scheme: HTTP
- initialDelaySeconds: 5
- periodSeconds: 10
- successThreshold: 1
- timeoutSeconds: 1
- serviceAccountName: kong-serviceaccount
我部署kong和konga的時候使用的是pgsql,根據GitHub上的文檔上說明得知,在使用NODE_ENV為production的時候需要手動去初始化pgsql。看了一下kong官網的文檔來初始化,官網文檔:https://docs.konghq.com/install/docker/
初始化pgsql報錯
- $ docker run --rm --network=kong-net -e "KONG_DATABASE=postgres" \
- > -e "KONG_PG_HOST=pgsql地址" \
- > -e "KONG_PG_USER=konga" \
- > -e "KONG_PG_PASSWORD=pgsql密碼" \
- > -e "KONG_PG_DATABASE=konga" \
- > -e "KONG_PG_PORT=3306" \
- > registry.ayunw.cn/kong/kong-custom:382-ffaf4d50 kong migrations up
- Unable to find image 'registry.ayunw.cn/kong/kong-custom:382-ffaf4d50' locally
- 382-ffaf4d50: Pulling from kong/kong-custom
- 0a6724ff3fcd: Pull complete
- 274efec6805c: Pull complete
- 4bb58967a4ce: Pull complete
- 3f59fb9af44b: Pull complete
- 7e3ec18b9226: Pull complete
- ce8acfac03f7: Pull complete
- Digest: sha256:453dea194d4e39275ea771d062262f0868e29120fc529702dea10278677413c2
- Status: Downloaded newer image for registry.ayunw.cn/kong/kong-custom:382-ffaf4d50
- Error: [PostgreSQL error] failed to retrieve PostgreSQL server_version_num: temporary failure in name resolution
- Run with --v (verbose) or --vv (debug) for more details
想了一下,他這個完全是docker部署kong而不是k8s中部署kong,因此他會需要創建一個docker的network為kong-net,然后保證所有kong相關的服務都跑在同一個網絡中。那我這里是部署在k8s中,且pgsql也是買的云的服務,所以我這里其實是不應該這樣子來進行初始化的。
然后上github,找到https://github.com/pantsel/konga/tree/master文檔上的Production Docker Image步驟中的Prepare the database來操作。
但是里面可能有一個參數解釋的不是很清楚,我自己一開始也是比較模糊的,就是https://github.com/pantsel/konga上Production Docker Image步驟下的Prepare the database步驟中的connection-uri參數,你會發現他似乎沒給出connection-uri的這個uri的例子是什么樣子的。但是其實你會發現在這個github中的Production步驟有寫一條url和這個比較類似的,告訴你在使用MySQL或者PostgresSQL的時候應該怎么初始化,命令是:node ./bin/konga.js prepare --adapter postgres --uri postgresql://localhost:5432/konga。但是注意,這個命令他應該不是在你將konga部署在k8s中來使用的。但是這里就有一條url:postgresql://localhost:5432/konga,可以用來參考,那么也就是說差不多就是這個樣子的url了,但是應該還需要帶上用戶名和密碼。
其實這里我還犯了一個錯誤,就是其實一開始我初始化的pgsql命令中pgsql的url寫錯了,看了https://github.com/pantsel/konga/tree/master中的文檔后,手敲命令,將postgresql://localhost:5432/konga敲成了postgre://localhost:5432/konga,所以初始化的時候也報錯了。
更改后重新初始化
- $ docker run registry.ayunw.cn/kube-system/pantsel/konga:0.14.9 -c prepare -a postgres -u postgresql://konga:pgsql密碼@pgsql地址:pgsql端口/konga
- debug: Preparing database...
- Using postgres DB Adapter.
- Failed to connect to DB Error: getaddrinfo EAI_AGAIN konga
- at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:64:26) {
- errno: 'EAI_AGAIN',
- code: 'EAI_AGAIN',
- syscall: 'getaddrinfo',
- hostname: 'konga'
- }
然后想到了因為“#”導致的問題。甚至嘗試了將密碼用單引號或者雙引號括起來嘗試,仍然報錯,然后將整個連接pgsql的url全部用單引號或者雙引號括起來,也都是沒有用。再查了一下google發現需要將“#”符號改成%23。
再次初始化
- $ docker run registry.ayunw.cn/kube-system/pantsel/konga:0.14.9 -c prepare -a postgres -u postgresql://konga:pgsql密碼@pgsql地址:pgsql端口/konga
- debug: Preparing database...
- Using postgres DB Adapter.
- Database exists. Continue...
- debug: Hook:api_health_checks:process() called
- debug: Hook:health_checks:process() called
- debug: Hook:start-scheduled-snapshots:process() called
- debug: Hook:upstream_health_checks:process() called
- debug: Hook:user_events_hook:process() called
- debug: Seeding User...
- debug: User seed planted
- debug: Seeding Kongnode...
- debug: Kongnode seed planted
- debug: Seeding Emailtransport...
- debug: Emailtransport seed planted
- debug: Database migrations completed!
初始化成功
總結部署konga遇到的問題
1、文檔中寫的connection-uri的話必須不能寫錯,postgresql不要寫成postgres
2、密碼中有符號“#”要改成%23
部署kong
- ---
- # Source: kong-custom-pre-master/templates/deployment.yaml
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: kong-custom-pre-master
- namespace: kong
- labels:
- appEnv: pre
- appName: kong-custom
- appGroup: kong
- spec:
- replicas: 1
- progressDeadlineSeconds: 1800
- minReadySeconds: 5
- strategy:
- type: RollingUpdate
- rollingUpdate:
- maxUnavailable: 50%
- maxSurge: 50%
- selector:
- matchLabels:
- appEnv: pre
- appName: kong-custom
- appGroup: kong
- template:
- metadata:
- labels:
- appEnv: pre
- appName: kong-custom
- appGroup: kong
- spec:
- dnsPolicy: ClusterFirst
- terminationGracePeriodSeconds: 10
- serviceAccountName: kong-serviceaccount
- imagePullSecrets:
- - name: registry-auth-kong-pro
- initContainers:
- - name: wait-for-migrations
- image: "registry.ayunw.cn/kong/kong-custom:398-c44f9085"
- command:
- - /bin/sh
- - -c
- - while true; do kong migrations bootstrap; if [[ 0 -eq 0 ]]; then exit 0; fi; sleep 2; done;
- env:
- # 注意這里KONG_DATABASE的value是錯誤的,應該將Kong改成postgres
- - name: KONG_DATABASE
- value: "kong"
- - name: KONG_PG_USER
- value: "kong"
- - name: KONG_PG_PORT
- value: "pgsql端口"
- - name: KONG_PG_PASSWORD
- value: "pgsql密碼"
- - name: KONG_PG_HOST
- value: "pgsql地址"
- containers:
- - name: kong-custom-pre-master
- image: "registry.ayunw.cn/kong/kong-custom:398-c44f9085"
- ports:
- - name: proxy
- containerPort: 8000
- protocol: TCP
- - name: proxy-ssl
- containerPort: 9443
- protocol: TCP
- - name: metrics
- containerPort: 8100
- protocol: TCP
- - name: admin-url
- containerPort: 8444
- protocol: TCP
- resources:
- limits:
- cpu: "5000m"
- memory: "1024Mi"
- requests:
- cpu: "100m"
- memory: "512Mi"
- lifecycle:
- preStop:
- exec:
- command:
- - /bin/sh
- - -c
- - kong quit
- env:
- - name: "KONG_PROXY_LISTEN"
- value: "0.0.0.0:8000, 0.0.0.0:9443 ssl http2"
- - name: "KONG_PORT_MAPS"
- value: "80:8000, 443:8443"
- - name: "KONG_ADMIN_LISTEN"
- value: "0.0.0.0:8444 ssl"
- - name: "KONG_STATUS_LISTEN"
- value: "0.0.0.0:8100"
- - name: "KONG_NGINX_WORKER_PROCESSES"
- value: "2"
- - name: "KONG_ADMIN_ACCESS_LOG"
- value: "/dev/stdout"
- - name: "KONG_ADMIN_ERROR_LOG"
- value: "/dev/stderr"
- - name: "KONG_PROXY_ERROR_LOG"
- value: "/dev/stderr"
- # 注意這里KONG_DATABASE的value是錯誤的,應該將Kong改成postgres
- - name: KONG_DATABASE
- value: "kong"
- - name: KONG_PG_USER
- value: "kong"
- - name: KONG_PG_PORT
- value: "pgsql端口"
- - name: KONG_PG_PASSWORD
- value: "pgsql密碼"
- - name: KONG_PG_HOST
- value: "pgsql地址"
查看kong的日志報錯
- $ kubectl logs -f --tail=20 -n kong kong-custom-sit-9c5cf7b69-4q29l
- stack traceback:
- [C]: in function 'error'
- /usr/local/share/lua/5.1/kong/cmd/utils/migrations.lua:16: in function 'check_state'
- /usr/local/share/lua/5.1/kong/init.lua:455: in function 'init'
- init_by_lua:3: in main chunk
- nginx: [error] init_by_lua error: /usr/local/share/lua/5.1/kong/cmd/utils/migrations.lua:16: Database needs bootstrapping or is older than Kong 1.0.
- To start a new installation from scratch, run 'kong migrations bootstrap'.
- To migrate from a version older than 1.0, migrated to Kong 1.5.0 first.
- If you still have 'apis' entities, you can convert them to Routes and Services
- using the 'kong migrations migrate-apis' command in Kong 1.5.0.
- stack traceback:
- [C]: in function 'error'
- /usr/local/share/lua/5.1/kong/cmd/utils/migrations.lua:16: in function 'check_state'
- /usr/local/share/lua/5.1/kong/init.lua:455: in function 'init'
- init_by_lua:3: in main chunk
很明顯是因為沒有執行kong migrations的命令。但是明明在deployment.yaml中的initContainers中已經寫了,為何沒執行?
原因
是因為kong的deployment.yaml中的initContainers下的env環境變量中KONG_DATABASE寫錯了,我寫成了kong。而根據github:https://github.com/pantsel/konga/tree/master上README.md文檔中的Environment variables中所知,KONG_DATABASE這個變量是要指明使用postgres或者MySQL或者off三個選項其中的一個。因為我用的是pgsql,因此這里需要指定postgres,那么初始化就回去pgsql中創建庫、表、創建數據等操作,這樣才會成功。
更改后,kong啟動正常。
寫在最后
我在konga的github上沒找到manifests直接可以用的yaml清單文件,只找到了chart包,因此我是渲染出來以后然后根據自己的實際環境進行了更改。初次使用難免會遇到雜七雜八的問題。其實也是由于我個人的不細心,沒仔細多看幾遍文檔導致的。有讀者如果找到了konga的manifests清單文件也可下方留言交流。也提醒各位小伙伴們,平常也需要注意一下習慣,減少和我犯同樣的錯誤!