使用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内部组件很是了解,对于没作过运维的我挑战很大,固然中间收获也不少😆。

相关文章
相关标签/搜索