22

用户数从0到亿,我的 K8s 踩坑血泪史

 5 years ago
source link: https://www.tuicool.com/articles/MjQf6fv
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

um2MfeZ.jpg!web

作者 | 平名 阿里服务端开发技术专家

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

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

创建集群

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

集群规划

1. 网络规划

  • 网络类型: Flannel、Terway[1]

Terway 是阿里云容器服务自研的网络插件,功能上完全兼容 Flannel,如果保守,还是使用 Flannel  

  • Pod 网络 CIDR

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

  • Service CIDR

默认 20 的网段,可选:10.0.0.0/16-24,172.16-31.0.0/16-24,192.168.0.0/16-24; 网段不能冲突重复,建立后没法修改;多个区域的多个交换机。

2. 公网访问 ApiServer

  • 对于线上等安全要求高的集群,可以选择不暴露 apiserver, 只有私网 SLB, 但是这样没法使用云效发布;

  • 日常预发等集群,可以暴露公网 SLB 到 apiserver, 集群建立后立即为 slb 建立访问控制,限制 slb 只能云效访问;

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

3. 安 全组

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

4. Master 机器规划

为了高可用,一般使用 3 节点,Master 选择规则[2] 如下:

节点数

master 规格

1-5个

4C8G

6-20个节点

4C16G

21-100个节点

8C32G

100-200个节点

16C64G

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

5. Worker 机器规划

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

  • 我们选用的机器配置:

    a. 32C64G ECS;

    b. 存储。系统盘:100G SSD,  数据盘:400G 高效云盘;

    c. 操作系统:centos 7.4 64 位。

集群建立与配置

1. 建立集群时设置:

  • 通过控制台建立集群,阿里云容器服务提供的非常简易的一键部署集群功能,通过向导完成 K8s 集群的建立;

  • 按照以上规划设置 master,worker 节点,挂载 /var/lib/docker 到数据盘;

  • 设置合理的 Pod 网络 CIDR, Service CIDR ip 网段;

  • 设置合理的安全策略,是否暴露 apiserver(需要直接云效发布的,需要开放公网暴露,并做严格的访问控制);

  • ingress 选择安全,可以使用内网,如果需要公网,可以在控制台很方便建立,同时做好访问控制;

  • kube-proxy 模式,因为 iptables 模式在更新一条规则时把 iptables 锁住引发的性能问题,建议使用 IPVS 模式;

  • 节点 POD 数量,默认 128 太大,一个节点不可能部署这么多,建议改为 64;

  • 节点服务端口访问 (NodePort,SLB),可以适当扩大,默认的也一般足够用。

2. 集群配置修改:

  • 集群扩容,添加已有节点(节点配置参考上文,挂载数据盘使用 /var/lib/docker) ;   

  • Master 机器升配;[3]

  • worker 节点变配或者移除:

    • kubectl drain --ignore-daemonsets {node.name};

    • kubectl delete node {node.name};

    • ECS 升配变配;

    • 添加已有节点到集群。

  • 命名空间: 

    • 按照应用分组建立 namespace,对于资源占用厉害需要限制的应用分组,设置该 NameSpace 的资源配额与限制。

  • 授权:

    • 子账号如何给其他子账号进行 RBAC 授权;[4]

    • 通过堡垒机按应用人员设置权限。[5]

部署设置

无状态部署

使用无状态部署 Deployment,参考[6] 实现分批发布。优化设置模板: 

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,并考虑负载均衡,需要遵守一定的配置规则和方法,参考[7]。

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、云监控、日志服务等,以应用为单位,提供更好服务。

相关链接

[1] https://yq.aliyun.com/articles/594943

[2] https://yq.aliyun.com/articles/599169?spm=a2c4e

[3] https://help.aliyun.com/document_detail/123661.html?spm=5176.10695662.1996646101.searchclickresult.2fc456efWdFrBF

[4] https://help.aliyun.com/document_detail/119035.html?spm=5176.2020520152.0.0.2b8c16ddCEYCf0

[5] https://yq.aliyun.com/articles/715809?spm=a2c4e.11155435.0.0.111f3312TcJgtj

[6] https://yq.aliyun.com/articles/715804?spm=a2c4e.11155435.0.0.111f3312TcJgtj

[7] https://yq.aliyun.com/articles/717073?spm=a2c4e.11153940.0.0.22841aa3WBD0v2

扫描下方二维码添加小助手,与 8000 位云原生爱好者讨论技术趋势,实战进阶!

进群暗号: 公司-岗位-城市

a2UNRrr.jpg!web

RECOMMEND

云原生推荐

aqeyEn6.jpg!web

euiQBje.jpg!web

vMVbyar.jpg!web

奖励看到最后的你

# 点下 在看 :heart:

# 然后,在公众号对话框内发送“ 牙刷 “,试试手气?

# 本期奖品是“ 淘宝心选便携电动牙刷 ”。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK