使用kops在aws寧夏區搭建k8s集羣

本文首發於個人bloghtml

最近使用kops在aws寧夏區搭建了一套生產用的k8s集羣,這裏說下完整的過程,包括中間遇到的各類坑。node

物料準備

  • 建立一個vpc
  • 建立一個S3的桶後面給kops存數據用
  • AmazonEC2FullAccess,AmazonRoute53FullAccess,AmazonS3FullAccess,IAMFullAccess,AmazonVPCFullAccess權限的IAM帳戶
  • 一臺低配的部署機器

配置部署機器

  • 安裝 kubectl,而且配置命令行自動補全 echo "source <(kubectl completion bash)" >> ~/.bashrc && source ~/.bashrc
  • download kops-cn,這個項目封裝了kops,把經常使用的鏡像放到寧夏區和北京區,你們不用費心再去配置代理拉取鏡像了,由於這個項目一直在更新而且沒有tag管理,我用的是此次commit,你們自行評估。
  • 安裝 kops(github.com/kubernetes/…),版本按照kops-cn要求的安裝便可

部署k8s集羣

就是按照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使用,具體參考這個issueapp

建立完畢以後能夠部署一個很簡單的應用上去,而後curl serviceName:serticePort,確保集羣能夠正常使用。運維

部署完畢以後,有三個master節點,分佈在三個可用區,這樣在一個可用區掛了的時候,集羣不受影響,還有兩個普通節點,屬於nodes這個instanceGroup(kops的一個概念,對應一個aws的autoscale組)。curl

經過elb接入外部流量

上面步驟成功以後,集羣內部的service能夠經過serviceName互相訪問了,若是要暴露出去給Internet訪問須要配置ingress。

咱們使用traefik-ingress做爲ingress controller,因此首先部署traefik:

部署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部署完畢便可。

準備application elb

上面建立集羣的時候kops會建立一個classic elb,咱們須要刪掉這個elb而後本身建立一個application elb,elb的流量轉發規則是任何到80端口上的流量,都要轉發到咱們上面建立的兩個node節點的31742端口(和traefik的監聽端口保持一致)。

而且配置好防火牆規則,elb能夠連通到該Node組。

因此,整個外部流量進入集羣的路徑是這樣的:

  1. 外部請求的客戶端經過dns查詢獲得咱們elb的ip
  2. 根據查詢到的ip流量會進入elb
  3. elb從咱們配置的轉發規則中的node中選擇一個,把流量導向該node的31742端口
  4. 流量到node的31742端口以後,由於traefik的hostPort: 31742的緣由,到31742端口的流量會由traefik-controller Pod處理
  5. traefik-controller 根據咱們的ingress資源,把流量導入某個service
  6. service從關聯的endpont資源中選擇一個Pod,把流量導入具體的Pod

這樣就完成了外部流量到Pod的整個過程。

部署過程的感覺

雖然有kops工具幫咱們簡化了這個過程,自建k8s集羣坑仍是多。好比咱們遇到了Node過一段時間就是NotReady致使node上的pod被驅逐,問題居然是AMI的問題,coreos對aws的多網卡的機器支持很差,換成debian系統就行了(如今kops-cn默認就是debian系統了)😁。

出了問題須要從aws服務一致排查到k8s內部組件,對debug能力要求很高,尤爲是須要對aws服務很是瞭解,對k8s內部組件很是瞭解,對於沒作過運維的我挑戰很大,固然中間收穫也不少😆。

相關文章
相關標籤/搜索