用户数从 0 到亿,个人 K8s 踩坑血泪史

file
做者 | 平名 阿里服务端开发技术专家html

导读:容器服务 Kubernetes 是目前煊赫一时的云原生基础设施,做者过去一年上线了一个用户数极速增加的应用:该应用一个月内日活用户从零至四千万,用户数从零到一亿的裂变式增加,充分享受了容器服务快速简便的扩容操做和高可用特性。做者使用容器服务 Kubernetes 集群将公司内系统彻底上云 1 年多,本篇文章记录了其中的踩坑与优化记录。

关注“阿里巴巴云原生”公众号,回复关键词“资料”,便可得到 2019 整年meetup 活动 PPT 合集及 K8s 最全知识图谱。node

建立集群

建立集群时,作好规划,选择优化好的集群配置,能够大大减小后期运维工做,其中部分集群的配置在创建后再也无法修改或者修改极其麻烦。docker

集群规划

            Terway 是阿里云容器服务自研的网络插件,功能上彻底兼容 Flannel,若是保守,仍是使用 Flannel  centos

  • Pod 网络 CIDR

默认 16 的大网段,有效的网段或者其子网 10.0.0.0/8,172.16-31.0.0/12-16,192.168.0.0/16api

    • Service CIDR安全

      • 默认 20 的网段,可选:10.0.0.0/16-24,172.16-31.0.0/16-24,192.168.0.0/16-24
      • 网段不能冲突重复,创建后无法修改;
      • 多个区域的多个交换机。
    • 公网访问 ApiServer服务器

      • 对于线上等安全要求高的集群,能够选择不暴露 apiserver, 只有私网 SLB, 可是这样无法使用云效发布;
      • 平常预发等集群,能够暴露公网 SLB 到 apiserver, 集群创建后当即为 slb 创建访问控制,限制 slb 只能云效访问;

    注: K8s 每次安全漏洞几乎都与 ApiServer 有关,对于线上 K8s 集群,要及时升级补丁,或者不开放公网 apiserver,使用严格的安全组和访问控制。网络

    • 安全组session

      • 设置安全组限定访问范围,为 master 与 worker 机器使用。

     

    • Master 机器规划

       为了高可用,通常使用 3 节点,Master 选择规则以下:

    节点数  master 规格
    1-5个 4C8G
    6-20个节点 4C16G
    21-100个节点 8C32G
    100-200个节点 16C64G

    master 机器的存储建议高性能的 50-100G SSD,由于会运行 ETCD,操做系统占用不超过 8G。

    • Worker 机器规划

      • 阿里云首推神龙机器,没有神龙机器的区域,选用高配 ECS,配置规格根据部署的 POD 规格乘以必定倍数,好比 Java 应用 pod 通常选择 4C8G,ECS 则购买 32C64G 或者 64C128G 为好,设置部署的时候为 pod 设置固定的 request/limit;
      • 咱们选用的机器配置:

        • 32C64G ECS
        • 存储。系统盘:100G SSD,  数据盘:400G 高效云盘
        • 操做系统:centos 7.4 64 位

    集群创建与配置

    创建集群时设置:

    • 经过控制台创建集群,阿里云容器服务提供的很是简易的一键部署集群功能,经过向导完成 K8S 集群的创建;
    • 按照以上规划设置 master,worker 节点,挂载 /var/lib/docker 到数据盘;
    • 设置合理的 Pod 网络 CIDR, Service CIDR ip 网段;
    • 设置合理的安全策略,是否暴露 apiserver(须要直接云效发布的,须要开放公网暴露,并作严格的访问控制);
    • ingress 选择安全,可使用内网,若是须要公网,能够在控制台很方便创建,同时作好访问控制;
    • kube-proxy 模式,由于 iptables 模式在更新一条规则时把 iptables 锁住引起的性能问题,建议使用 IPVS 模式;
    • 节点 POD 数量,默认 128 太大,一个节点不可能部署这么多,建议改成 64;
    • 节点服务端口访问 (NodePort,SLB),能够适当扩大,默认的也通常足够用。

    集群配置修改:

    部署设置

    无状态部署

    使用无状态部署 Deployment,参考这篇文章实现分批发布
    优化设置模板: 

    apiVersion: apps/v1beta2
    kind: Deployment
    metadata:
      annotations:
        deployment.kubernetes.io/revision: '34'
    # 标签,映射 service
      labels:
        app: {app_name}-aone
      name: {app_name}-aone-1
      namespace: {app_name}
    spec:
      progressDeadlineSeconds: 600
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: {app_name}-aone
    # 批量重启更新策略      
      strategy:
        rollingUpdate:
          maxSurge: 25%
          maxUnavailable: 25%
        type: RollingUpdate
      template:
        metadata:
          labels:
            app: {app_name}-aone
        spec:
          containers:
           # 环境变量增长时区
            - env:
                - name: TZ
                  value: Asia/Shanghai
            - image: >-
                registry-vpc.cn-north-2-gov-1.aliyuncs.com/{namespace}/{app_name}:20190820190005
              imagePullPolicy: Always
              # 启动前执行优雅下线摘除 服务注册
              lifecycle:
                preStop:
                  exec:
                    command:
                      - sudo
                      - '-u'
                      - admin
                      - /home/{user_name}/{app_name}/bin/appctl.sh
                      - {app_name}
                      - stop
              # 存活检查,强烈建议设置        
              livenessProbe:
                failureThreshold: 10
                initialDelaySeconds: 30
                periodSeconds: 10
                successThreshold: 1
                tcpSocket:
                  port: 5900
                timeoutSeconds: 1
              name: {app_name}-aone
              # 就绪检查,强烈建议设置
              readinessProbe:
                failureThreshold: 10
                initialDelaySeconds: 30
                periodSeconds: 10
                successThreshold: 1
                tcpSocket:
                  port: 5900
                timeoutSeconds: 1
              # 资源限制,这个必定要合理设置  
              resources:
                limits:
                  cpu: '4'
                  memory: 8Gi
                requests:
                  cpu: '4'
                  memory: 8Gi
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              # 日志存放目录,映射到节点的/var/lib/docker/logs 数据盘,应用日志目录设置到/home/{user_name}/logs 下
              volumeMounts:
                - mountPath: /home/{user_name}/logs
                  name: volume-1553755418538
          dnsPolicy: ClusterFirst
          ## 私有镜像仓库的密钥,从保密字段获取
          imagePullSecrets:
            - name: {app_name}-987
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
          # 日志存放目录,映射到节点的/var/lib/docker/logs 数据盘
          volumes:
            - hostPath:
                path: /var/lib/docker/logs/{app_name}
                type: ''
              name: volume-1553755418538

     

    服务设置

    由于容器服务的 Cloud Controller Manager 会同步删除 service 创建关联的 SLB,为了防止 service 配置修改误删除 slb 故障,并致使域名、安全等配置须要修改的坑,强烈建议 service 与 slb 解耦,service 采用 NodePort 的方式,slb 另外创建后端服务器指向集群节点,若是须要透传真实 IP,并考虑负载均衡,须要遵照必定的配置规则和方法,参考这个文章

    NodePort:

    apiVersion: v1
    kind: Service
    metadata:
      name: {app_name}
      namespace: {namespaces}
    spec:
      clusterIP: 10.1.50.65
    ## 策略关系到是否透传真实 IP
      externalTrafficPolicy: Cluster
      ports:
        - name:  {app_name}-80-7001
          nodePort: 32653
          port: 80
          protocol: TCP
          targetPort: 7001
        - name:  {app_name}-5908-5908
          nodePort: 30835
          port: 5108
          protocol: TCP
          targetPort: 5108
      selector:
        app:  {app_name}
      sessionAffinity: None
      type: NodePort
    status:
      loadBalancer: {}

    而后在负载均衡管理页面,选择后端服务器指向集群的 worker 机器,设置端口为以上服务的端口:32653,完成配置,这样在集群 service 修改或者删除重建的时候,slb 不会被集群的 CCM 删除,不会涉及到域名,安全等配置修改。同时,能够设置一些策略,须要升级修改服务配置时,分批切流等。

    总结

    阿里云容器服务控制台虽然是云上新产品,提供了极其简单的一键部署功能,以及简便的控制台管理。过去一年中,笔者一路见识阿里云容器服务控制台从简陋向强大的转变过程,虽然屡次踩坑,但阿里云容器服务同窗认真负责和极好的服务态度让人佩服。

    容器服务管理控制台还须要更多的考虑实际运维需求,并紧密结合已有的云产品,好比云效、EDAS、云监控、日志服务等,以应用为单位,提供更好服务。



    扫描下方二维码添加小助手,与 8000 位云原生爱好者讨论技术趋势,实战进阶!
    进群暗号:公司-岗位-城市

    file搜索「阿里巴巴云原生公众号」获取更多K8s容器技术内容

    相关文章
    相关标签/搜索