k8s ipv6 双栈集群 公众组件适配方案

本贴最后更新于 637 天前,其中的信息可能已经时移世改

背景

k8s: ipv4/ipv6 双栈

  1. 服务规约中没有显式设定 .spec.ipFamilyPolicy 。当你创建此服务时,Kubernetes 从所配置的第一个 service-cluster-ip-range 种为服务分配一个集群 IP,并设置 .spec.ipFamilyPolicySingleStack
  2. .spec.ipFamilyPolicy 设置为 PreferDualStack
    • 当你在双栈集群上创建此服务时,Kubernetes 会为该服务分配 IPv4 和 IPv6 地址。 控制平面更新服务的 .spec 以记录 IP 地址分配。 字段 .spec.ClusterIPs 是主要字段,包含两个分配的 IP 地址; .spec.ClusterIP 是次要字段, 其取值从 .spec.ClusterIPs 计算而来。
    • 对于单协议栈的集群, .spec.ClusterIPs.spec.ClusterIP 字段都 仅仅列出一个地址。

通用方案

  1. charts 中 service 相关的模板需要暴露 .spec.ipFamilyPolicy 字段,在 values.yaml 中显示指定。采用 kyverno 去注入这个字段,而不是批量修改 charts。
# 查找Service模板文件
grep -irw "kind: Service" -R
  1. 确保公众组件能同时监听 0.0.0.0:: 地址。内部服务可以直接通过 ipv6 通信。(可以关闭 coredns 的 ipv4 解析来测试)

    在验证服务是从 ipv6 的域名解析访问的,coredns 需要修改配置,将 A 的请求,重定向到 AAAA,这样可以保证只通过访问 ipv6 服务。

    .:53 {
            rewrite stop type A AAAA
    }
    
  2. 外部应用能访问公众组件 ipv6 服务。

  3. 对于公众组件的集群模式,集群内通信端口需要能支持 ipv6 通信。(这个不大好验证)

kyverno 字段注入

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno --version v2.5.1 -n kyverno --create-namespace

  创建集群策略 ipv6-policy.yaml,kubectl apply -f ipv6-policy.yaml

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-ipfamily
  annotations:
    policies.kyverno.io/title: Add IP Family
    policies.kyverno.io/category: Sample
    policies.kyverno.io/severity: medium
    policies.kyverno.io/subject: ipFamily
spec:
  rules:
  - name: add-ipfamily
    match:
      resources:
        kinds:
        - Service
    mutate:
      patchStrategicMerge:
        spec:
          ipFamilyPolicy: PreferDualStack

kyverno 策略验证

创建 python 服务,不显示指定 ipFamilyPolicy。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: python-deployment
  labels:
    app: python-http
spec:
  replicas: 1
  selector:
    matchLabels:
      app: python-http
  template:
    metadata:
      labels:
        app: python-http
    spec:
      containers:
      - name: python-http
        image: python:3.8.13-slim
        ports:
        - containerPort: 8080
        command: ["python"]
        args: ["-m","http.server","8080","--bind","::"]
---
apiVersion: v1
kind: Service
metadata:
  name: python-service
spec:
  selector:
    app: python-http
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080

  查看 python-service 的.spec.ipFamilyPolicy 字段,注入成功,验证通过!

➜ kubectl get svc python-service -o yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"python-service","namespace":"default"},"spec":{"ports":[{"port":8080,"protocol":"TCP","targetPort":8080}],"selector":{"app":"python-http"}}}
    policies.kyverno.io/last-applied-patches: |
      add-ipfamily.add-ipfamily.kyverno.io: added /spec/ipFamilyPolicy
  creationTimestamp: "2022-07-18T12:07:52Z"
  name: python-service
  namespace: default
  resourceVersion: "4662253"
  uid: e1ab7dd7-688c-4db1-b033-034651537a27
spec:
  clusterIP: 10.110.61.121
  clusterIPs:
  - 10.110.61.121
  - fd00::1234:5678:1:c603
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  - IPv6
  ipFamilyPolicy: PreferDualStack
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: python-http
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

ingress-controller

  适配的版本见# Ingress NGINX Controller,选择 charts 4.1.2,ingress 为 1.2.0

helmfile -f /data/bkhelmfile/blueking/ingress-nginx-1.2.0.gotmpl sync

  values 配置 controller.service.ipFamilies=["ipv6"] 才能设置为 ipv6 单栈模式。

mysql

  chart:bitnami/mysql-4.5.5

  覆盖 values.yaml 中 master.config 和 slave.config 中的 bind-address,绑定至全端口

master:
  config: |-
    [mysqld]
    bind-address=*    
slave:
  config: |-
    [mysqld]
    bind-address=*    

rabbitmq

  chart: bitnami/rabbitmq-8.24.12

https://www.rabbitmq.com/management.html#single-listener-port,rabbitmq 是支持双栈监听的
empd 默认监听 ipv6.
rabbitmq: networking
By default, RabbitMQ will listen on port 5672 on all available interfaces. It is possible to limit client connections to a subset of the interfaces or even just one, for example, IPv6-only interfaces. The following few sections demonstrate how to do it.

  rbmq 的 HTTP API 客户端 15672,没有监听 ipv6

https://rabbitmq.com/rabbitmq-server.8.html
RABBITMQ_NODE_IP_ADDRESSBy default RabbitMQ will bind to all IPv6 and IPv4 interfaces available. This variable limits the node to one network interface or address family. To learn more, see the RabbitMQ Networking guide

  解决方法:

extraConfiguration: |-
  management.tcp.port = 15672
  management.tcp.ip  = ::  

rabbitmq 集群内部通过 ipv6 通信(端口 25672)需要配置开启,见 rabbitmq-networking-distribution-ipv6注意集群通信端口只能选择 ipv4、ipv6 中的一种方式通信
在 ipv6 单栈集群,如果需要开启 rbmq 的集群模式,需要通过:github #issues/6845 解决,如下

initContainers:
- name: rabbitmq-ipv6-init
  image: "docker.io/busybox:1.33.1"
  imagePullPolicy: IfNotPresent
  volumeMounts:
  - name: rabbitmq-ipv6-cfg
    mountPath: /ipv6
  command: ['sh', '-c', 'echo "{inet6, true}." > /ipv6/erl_inetrc']
extraVolumes:
- name: rabbitmq-ipv6-cfg
  emptyDir: {}
extraVolumeMounts:
- name: rabbitmq-ipv6-cfg
  mountPath: /ipv6
extraEnvVars:
- name: RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS
  value: "-kernel inetrc '/ipv6/erl_inetrc' -proto_dist inet6_tcp"
- name: RABBITMQ_CTL_ERL_ARGS
  value: "-proto_dist inet6_tcp"

redis

  chart bitnami/redis-15.3.3

  redis: config 中,可以看到在 redis6.2 中 bind 127.0.0.1 -::1,默认同时监听 ipv4/ipv6 地址。

redis-cluster

  chart: bitnami/redis-cluster-7.4.6
和 redis 一致

mongodb

  chart:bitnami/mongodb-10.30.6

mongodb: 参考 > 安全 > 网络和配置强化 > IP 绑定 ,需要手动绑定 ipv6。
从 MongoDB 3.6,MongoDB 二进制文件mongod和开始 mongos,默认情况下绑定到 localhost。如果 为二进制net.ipv6文件设置了 配置文件设置或 --ipv6 命令行选项,则二进制文件还会绑定到本地 IPv6 地址。

  在 values.yaml 中,提供了开启 ipv6 的 values,无需通过 Values.configuration 修改配置文件。

# values.yaml
enableIPv6: true

elastic

  chart:bitnami/elasticsearch-17.5.4

  Indexing IPv6 addresses in Elasticsearch,elastic 已支持 ipv6。

Starting with Elasticsearch 5.0, the ip field will support indexing IPv6 addresses.
elastic7.16: IP field type。 An ip field can index/store either IPv4 or IPv6 addresses.

zookeeper

  chart:bitnami/zookeeper-9.0.4

  zookeeperAdmin Guide: A Guide to Deployment and Administration,zk 已支持 ipv6。

clientPortAddressNew in 3.3.0: the address (ipv4, ipv6 or hostname) to listen for client connections; that is, the address that clients attempt to connect to. This is optional, by default we bind in such a way that any connection to the clientPort for any address/interface/nic on the server will be accepted.

因为未开启集群模式, leader 监听端 ipv6 口 2888 和集群内通信 3888 端口是关闭的

etcd

  chart bitnami/etcd-6.2.11 (bcs-system 依赖)
无需额外配置,默认支持 ipv6。

  

  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    476 引用 • 899 回帖 • 3 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    108 引用 • 54 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...