1 - Додавання записів до файлу /etc/hosts у Pod за допомогою HostAliases

Додавання записів до файлу /etc/hosts у Pod надає можливість перевизначення розподілу імен на рівні Pod, коли DNS та інші параметри не застосовуються. Ви можете додавати ці власні записи за допомогою поля HostAliases у PodSpec.

Не рекомендується вносити зміни без використання HostAliases, оскільки файл керується kubelet і може бути перезаписаний під час створення/перезапуску Pod.

Типовий вміст файлу hosts

Запустіть Pod з Nginx, який має призначену IP-адресу Podʼа:

kubectl run nginx --image nginx
pod/nginx created

Перевірте IP-адресу Podʼа:

kubectl get pods --output=wide
NAME     READY     STATUS    RESTARTS   AGE    IP           NODE
nginx    1/1       Running   0          13s    10.200.0.4   worker0

Вміст файлу hosts буде виглядати так:

kubectl exec nginx -- cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
fe00::0	ip6-mcastprefix
fe00::1	ip6-allnodes
fe00::2	ip6-allrouters
10.200.0.4	nginx

Типово файл hosts містить тільки шаблони IPv4 та IPv6, такі як localhost та власне імʼя хосту.

Додавання додаткових записів за допомогою hostAliases

Крім стандартних шаблонів, ви можете додати додаткові записи до файлу hosts. Наприклад: щоб перевести foo.local, bar.local в 127.0.0.1 та foo.remote, bar.remote в 10.1.2.3, ви можете налаштувати HostAliases для Pod в підполі .spec.hostAliases:

apiVersion: v1
kind: Pod
metadata:
  name: hostaliases-pod
spec:
  restartPolicy: Never
  hostAliases:
  - ip: "127.0.0.1"
    hostnames:
    - "foo.local"
    - "bar.local"
  - ip: "10.1.2.3"
    hostnames:
    - "foo.remote"
    - "bar.remote"
  containers:
  - name: cat-hosts
    image: busybox:1.28
    command:
    - cat
    args:
    - "/etc/hosts"

Ви можете запустити Pod з такою конфігурацією, виконавши:

kubectl apply -f https://k8s.io/examples/service/networking/hostaliases-pod.yaml
pod/hostaliases-pod created

Перевірте деталі Pod, щоб побачити його IPv4-адресу та статус:

kubectl get pod --output=wide
NAME                           READY     STATUS      RESTARTS   AGE       IP              NODE
hostaliases-pod                0/1       Completed   0          6s        10.200.0.5      worker0

Вміст файлу hosts виглядає так:

kubectl logs hostaliases-pod
# Kubernetes-managed hosts file.
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
fe00::0	ip6-mcastprefix
fe00::1	ip6-allnodes
fe00::2	ip6-allrouters
10.200.0.5	hostaliases-pod

# Entries added by HostAliases.
127.0.0.1	foo.local	bar.local
10.1.2.3	foo.remote	bar.remote

з додатковими записами, вказаними внизу.

Чому kubelet керує файлом hosts?

kubelet керує файлом hosts для кожного контейнера Podʼа, щоб запобігти модифікації файлу контейнерним середовищем після того, як контейнери вже були запущені. Історично Kubernetes завжди використовував Docker Engine як своє контейнерне середовище, і Docker Engine модифікував файл /etc/hosts після запуску кожного контейнера.

Поточна версія Kubernetes може використовувати різні контейнерні середовища; проте, kubelet керує файлом hosts у кожному контейнері, щоб результат був таким, як очікувалося, незалежно від використаного контейнерного середовища.

2 - Розширення діапазонів IP Service

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.27 [alpha]

У цьому документі описано, як розширити наявний діапазон IP-адрес, призначених Serviceʼу в кластері.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Версія вашого Kubernetes сервера має бути не старішою ніж v1.29. Для перевірки версії введіть kubectl version.

API

Кластери Kubernetes з kube-apiservers, у яких увімкнено feature gate MultiCIDRServiceAllocator та API networking.k8s.io/v1alpha1, створюватимуть новий обʼєкт ServiceCIDR, який має відоме імʼя kubernetes, та використовуватимуть діапазон IP-адрес, заснований на значенні аргументу командного рядка --service-cluster-ip-range для kube-apiserver.

kubectl get servicecidr
NAME         CIDRS          AGE
kubernetes   10.96.0.0/28   17d

Відомий сервіс kubernetes, який використовується для відкриття точки доступу kube-apiserver для Podʼів, обчислює першу IP-адресу зі стандартного діапазону ServiceCIDR та використовує цю IP-адресу як свою кластерну IP-адресу.

kubectl get service kubernetes
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   17d

Стандартний Service у цьому випадку використовує ClusterIP 10.96.0.1, що має відповідний обʼєкт IPAddress.

kubectl get ipaddress 10.96.0.1
NAME        PARENTREF
10.96.0.1   services/default/kubernetes

ServiceCIDRs захищені за допомогою завершувачів, щоб уникнути залишання Service ClusterIPs сиріт; завершувач видаляється лише в разі, якщо існує інша підмережа, яка містить наявні IP-адреси або немає IP-адрес, що належать до підмережі.

Розширення кількості доступних IP для Service

Існують випадки, коли користувачам потрібно збільшити кількість доступних адрес для Serviceʼів; раніше, збільшення діапазону Service було руйнівною операцією, яка також може призвести до втрати даних. З цією новою функцією користувачам потрібно лише додати новий ServiceCIDR, щоб збільшити кількість доступних адрес.

Додавання нового ServiceCIDR

У кластері з діапазоном 10.96.0.0/28 для Serviceʼів доступно лише 2^(32-28) - 2 = 14 IP-адрес. Service kubernetes.default завжди створюється; для цього прикладу у вас залишається лише 13 можливих Serviceʼів.

for i in $(seq 1 13); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
10.96.0.11
10.96.0.5
10.96.0.12
10.96.0.13
10.96.0.14
10.96.0.2
10.96.0.3
10.96.0.4
10.96.0.6
10.96.0.7
10.96.0.8
10.96.0.9
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full

Ви можете збільшити кількість IP-адрес, доступних для Serviceʼів, створивши новий ServiceCIDR, який розширює або додає нові діапазони IP-адрес.

cat <EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1alpha1
kind: ServiceCIDR
metadata:
  name: newcidr1
spec:
  cidrs:
  - 10.96.0.0/24
EOF
servicecidr.networking.k8s.io/newcidr1 created

це дозволить вам створювати нові Service з ClusterIP, які будуть вибрані з цього нового діапазону.

for i in $(seq 13 16); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
10.96.0.48
10.96.0.200
10.96.0.121
10.96.0.144

Видалення ServiceCIDR

Ви не можете видалити ServiceCIDR, якщо існують IP-адреси, які залежать від ServiceCIDR.

kubectl delete servicecidr newcidr1
servicecidr.networking.k8s.io "newcidr1" deleted

Kubernetes використовує завершувач на ServiceCIDR для відстеження цього залежного відношення.

kubectl get servicecidr newcidr1 -o yaml
apiVersion: networking.k8s.io/v1alpha1
kind: ServiceCIDR
metadata:
  creationTimestamp: "2023-10-12T15:11:07Z"
  deletionGracePeriodSeconds: 0
  deletionTimestamp: "2023-10-12T15:12:45Z"
  finalizers:
  - networking.k8s.io/service-cidr-finalizer
  name: newcidr1
  resourceVersion: "1133"
  uid: 5ffd8afe-c78f-4e60-ae76-cec448a8af40
spec:
  cidrs:
  - 10.96.0.0/24
status:
  conditions:
  - lastTransitionTime: "2023-10-12T15:12:45Z"
    message: There are still IPAddresses referencing the ServiceCIDR, please remove
      them or create a new ServiceCIDR
    reason: OrphanIPAddress
    status: "False"
    type: Ready

Видаляючи Serviceʼи, що містять IP-адреси, які блокують видалення ServiceCIDR

for i in $(seq 13 16); do kubectl delete service "test-$i" ; done
service "test-13" deleted
service "test-14" deleted
service "test-15" deleted
service "test-16" deleted

панель управління помічає видалення. Панель управління потім видаляє свій завершувач, так що ServiceCIDR, який був у черзі на видалення, фактично буде видалено.

kubectl get servicecidr newcidr1
Error from server (NotFound): servicecidrs.networking.k8s.io "newcidr1" not found

3 - Перевірка наявності підтримки подвійного стеку IPv4/IPv6

Цей документ розповідає, як перевірити підтримку dual-stack IPv4/IPv6 в увімкнених кластерах Kubernetes.

Перш ніж ви розпочнете

  • Підтримка постачальника для мереж з підтримкою подвійного стека (постачальник хмарних послуг або інший постачальник повинен забезпечити вузлам Kubernetes мережеві інтерфейси з маршрутними IPv4/IPv6)
  • Втулок мережі, який підтримує dual-stack мережу.
  • Увімкнений подвійний стек кластер
Версія вашого Kubernetes сервера має бути не старішою ніж v1.23. Для перевірки версії введіть kubectl version.

Перевірка адресації

Перевірка адресування вузлів

Кожен вузол з подвійним стеком має мати виділені один блок IPv4 та один блок IPv6. Перевірте, що діапазони адрес IPv4/IPv6 для Pod налаштовані за допомогою наступної команди. Замініть імʼя вузла з прикладу на наявний вузол з подвійним стеком у вашому кластері. У цьому прикладі імʼя вузла — k8s-linuxpool1-34450317-0:

kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .spec.podCIDRs}}{{printf "%s\n" .}}{{end}}'
10.244.1.0/24
2001:db8::/64

Має бути виділено один блок IPv4 та один блок IPv6.

Перевірте, що на вузлі виявлено інтерфейс IPv4 та IPv6. Замініть ім'я вузла на дійсний вузол з кластера. У цьому прикладі ім'я вузла - k8s-linuxpool1-34450317-0:

kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .status.addresses}}{{printf "%s: %s\n" .type .address}}{{end}}'
Hostname: k8s-linuxpool1-34450317-0
InternalIP: 10.0.0.5
InternalIP: 2001:db8:10::5

Перевірка адресації Pod

Перевірте, що у Pod є призначена адреса IPv4 та IPv6. Замініть імʼя Pod на наявний Pod у вашому кластері. У цьому прикладі ім'я Pod - pod01:

kubectl get pods pod01 -o go-template --template='{{range .status.podIPs}}{{printf "%s\n" .ip}}{{end}}'
10.244.1.4
2001:db8::4

Ви також можете перевірити IP-адреси Pod за допомогою Downward API через поле .status.podIPs. Наступний уривок показує, як ви можете використовувати IP-адреси Pod через змінну середовища з назвою MY_POD_IPS всередині контейнера.

        env:
        - name: MY_POD_IPS
          valueFrom:
            fieldRef:
              fieldPath: status.podIPs

Наступна команда виводить значення змінної середовища MY_POD_IPS всередині контейнера. Значення — це кома, що розділяє список, який відповідає IPv4 та IPv6 адресам Pod.

kubectl exec -it pod01 -- set | grep MY_POD_IPS
MY_POD_IPS=10.244.1.4,2001:db8::4

IP-адреси Pod також будуть записані в /etc/hosts всередині контейнера. Наступна команда виконує cat на /etc/hosts в Podʼі з подвійним стеком. З виводу ви можете перевірити як IPv4, так і IPv6 IP-адресу для Pod.

kubectl exec -it pod01 -- cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
fe00::0    ip6-mcastprefix
fe00::1    ip6-allnodes
fe00::2    ip6-allrouters
10.244.1.4    pod01
2001:db8::4    pod01

Перевірка Serviceʼів

Створіть наступний Service, який не визначає явно .spec.ipFamilyPolicy. Kubernetes призначить кластерний IP для Service з першого налаштованого service-cluster-ip-range і встановить .spec.ipFamilyPolicy на SingleStack.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app.kubernetes.io/name: MyApp
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80

Використовуйте kubectl, щоб переглянути YAML для Service.

kubectl get svc my-service -o yaml

У Service .spec.ipFamilyPolicy встановлено на SingleStack, а .spec.clusterIP встановлено на IPv4-адрес з першого налаштованого діапазону, встановленого за допомогою прапорця --service-cluster-ip-range на kube-controller-manager.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: default
spec:
  clusterIP: 10.0.217.164
  clusterIPs:
  - 10.0.217.164
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - port: 80
    protocol: TCP
    targetPort: 9376
  selector:
    app.kubernetes.io/name: MyApp
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

Створіть наступний Service, який явно визначає IPv6 як перший елемент масиву в .spec.ipFamilies. Kubernetes призначить кластерний IP для Service з діапазону IPv6, налаштованого в service-cluster-ip-range, і встановить .spec.ipFamilyPolicy на SingleStack.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app.kubernetes.io/name: MyApp
spec:
  ipFamilies:
  - IPv6
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80

Використовуйте kubectl, щоб переглянути YAML для Service.

kubectl get svc my-service -o yaml

У Service .spec.ipFamilyPolicy встановлено на SingleStack, а .spec.clusterIP встановлено на IPv6-адрес з діапазону IPv6, налаштованого за допомогою прапорця --service-cluster-ip-range у kube-controller-manager.

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: MyApp
  name: my-service
spec:
  clusterIP: 2001:db8:fd00::5118
  clusterIPs:
  - 2001:db8:fd00::5118
  ipFamilies:
  - IPv6
  ipFamilyPolicy: SingleStack
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app.kubernetes.io/name: MyApp
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

Створіть наступний Service, який явно визначає PreferDualStack в .spec.ipFamilyPolicy. Kubernetes призначить як IPv4, так і IPv6 адреси кластера (оскільки в цьому кластері ввімкнено подвійний стек) і вибере .spec.ClusterIP зі списку .spec.ClusterIPs на основі сімʼї адрес, що вказана в першому елементі масиву .spec.ipFamilies.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app.kubernetes.io/name: MyApp
spec:
  ipFamilyPolicy: PreferDualStack
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80

Перевірте, що Service отримує кластерні IP з діапазонів IPv4 та IPv6, використовуючи kubectl describe. Потім ви можете перевірити доступ до Service за допомогою IP та портів.

kubectl describe svc -l app.kubernetes.io/name=MyApp
Name:              my-service
Namespace:         default
Labels:            app.kubernetes.io/name=MyApp
Annotations:       <none>
Selector:          app.kubernetes.io/name=MyApp
Type:              ClusterIP
IP Family Policy:  PreferDualStack
IP Families:       IPv4,IPv6
IP:                10.0.216.242
IPs:               10.0.216.242,2001:db8:fd00::af55
Port:              <unset>  80/TCP
TargetPort:        9376/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

Створення Service з подвійним стеком для балансування навантаження

Якщо постачальник хмарних послуг підтримує надання зовнішніх балансувальників навантаження з підтримкою IPv6, створіть наступний Service з PreferDualStack в .spec.ipFamilyPolicy, IPv6 як перший елемент масиву .spec.ipFamilies, а також встановіть поле type на LoadBalancer.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app.kubernetes.io/name: MyApp
spec:
  ipFamilyPolicy: PreferDualStack
  ipFamilies:
  - IPv6
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80

Перевірка Service:

kubectl get svc -l app.kubernetes.io/name=MyApp

Перевірте, що Service отримує CLUSTER-IP адресу з блоку адрес IPv6 разом із EXTERNAL-IP. Потім ви можете перевірити доступ до Service за допомогою IP та портів.

NAME         TYPE           CLUSTER-IP            EXTERNAL-IP        PORT(S)        AGE
my-service   LoadBalancer   2001:db8:fd00::7ebc   2603:1030:805::5   80:30790/TCP   35s