本文首發於個人bloghtml
最近使用kops在aws寧夏區搭建了一套生產用的k8s集羣,這裏說下完整的過程,包括中間遇到的各類坑。node
AmazonEC2FullAccess,AmazonRoute53FullAccess,AmazonS3FullAccess,IAMFullAccess,AmazonVPCFullAccess
權限的IAM帳戶echo "source <(kubectl completion bash)" >> ~/.bashrc && source ~/.bashrc
就是按照kopsc-cn的文檔來就能夠了,說下文檔沒有提到的幾點:git
Makefile中有這麼一段代碼:github
ifeq ($(TARGET_REGION) ,cn-northwest-1)
CLUSTER_NAME ?= cluster.zhy.k8s.local
# copy from kope.io/k8s-1.12-debian-stretch-amd64-hvm-ebs-2019-05-13
# see https://github.com/nwcdlabs/kops-cn/issues/96
AMI ?= ami-068b32c3754324d44
ZONES ?= cn-northwest-1a,cn-northwest-1b,cn-northwest-1c
endif
複製代碼
這個CLUSTER_NAME
要修改一下,否則建立出來集羣名字就是cluster.zhy.k8s.local
,特別怪異。web
執行make edit-cluster
的時候能夠修改下子網CIDR,默認子網是/16
,咱們修改爲了/24
,緣由是咱們在vpc中已經建立了一個子網來放部署機和跳板機,若是/16
的話會形成子網IP段衝突。api
若是新建的集羣要刪除重建的話,在執行了make validate-cluster
以後須要手動檢查下 ELB,subnet,routetable,EC2是否刪除乾淨,而且清除.kube
文件夾。bash
默認建立的子網是public的,若是須要建立private的,能夠本身建立private subnet和NAT,而後傳給kops使用,具體參考這個issue。app
建立完畢以後能夠部署一個很簡單的應用上去,而後curl serviceName:serticePort
,確保集羣能夠正常使用。運維
部署完畢以後,有三個master節點,分佈在三個可用區,這樣在一個可用區掛了的時候,集羣不受影響,還有兩個普通節點,屬於nodes
這個instanceGroup(kops的一個概念,對應一個aws的autoscale組)。curl
上面步驟成功以後,集羣內部的service能夠經過serviceName互相訪問了,若是要暴露出去給Internet訪問須要配置ingress。
咱們使用traefik-ingress做爲ingress controller,因此首先部署traefik:
準備traefik使用的RBAC role文件: traefik-rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
複製代碼
執行 kubectl apply -f traefik-rbac.yaml
使用Demonset的方式部署traefik,準備 traefik.yaml:
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
hostPort: 31742
- name: admin
containerPort: 8080
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
args:
- --api
- --kubernetes
- --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
複製代碼
注意hostPort: 31742
這一句,很是關鍵,指的是到該Pod所在的Node的31742端口的流量,自動轉交給該Pod處理。若是31742已經被佔用了,能夠換一個端口。
最後執行kubectl apply -f traefik.yaml
,而後執行kubectl -n kube-system get pod -w
,等待traefik-controller部署完畢便可。
上面建立集羣的時候kops會建立一個classic elb,咱們須要刪掉這個elb而後本身建立一個application elb,elb的流量轉發規則是任何到80端口上的流量,都要轉發到咱們上面建立的兩個node節點的31742端口(和traefik的監聽端口保持一致)。
而且配置好防火牆規則,elb能夠連通到該Node組。
因此,整個外部流量進入集羣的路徑是這樣的:
hostPort: 31742
的緣由,到31742端口的流量會由traefik-controller Pod處理這樣就完成了外部流量到Pod的整個過程。
雖然有kops工具幫咱們簡化了這個過程,自建k8s集羣坑仍是多。好比咱們遇到了Node過一段時間就是NotReady
致使node上的pod被驅逐,問題居然是AMI的問題,coreos對aws的多網卡的機器支持很差,換成debian系統就行了(如今kops-cn默認就是debian系統了)😁。
出了問題須要從aws服務一致排查到k8s內部組件,對debug能力要求很高,尤爲是須要對aws服務很是瞭解,對k8s內部組件很是瞭解,對於沒作過運維的我挑戰很大,固然中間收穫也不少😆。