1 - HostAliases로 파드의 /etc/hosts 항목 추가하기
파드의 /etc/hosts 파일에 항목을 추가하는 것은 DNS나 다른 방법들이 적용되지 않을 때 파드 수준의 호스트네임 해석을 제공한다. PodSpec의 HostAliases 항목을 사용하여 이러한 사용자 정의 항목들을 추가할 수 있다.
HostAliases를 사용하지 않은 수정은 권장하지 않는데, 이는 호스트 파일이 kubelet에 의해 관리되고, 파드 생성/재시작 중에 덮어쓰여질 수 있기 때문이다.
기본 호스트 파일 내용
파드 IP가 할당된 Nginx 파드를 시작한다.
kubectl run nginx --image nginx
pod/nginx created
파드 IP를 확인해보자.
kubectl get pods --output=wide
NAME     READY     STATUS    RESTARTS   AGE    IP           NODE
nginx    1/1       Running   0          13s    10.200.0.4   worker0
호스트 파일의 내용은 아래와 같을 것이다.
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 파일은 localhost와 자기 자신의 호스트네임과 같은 IPv4와 IPv6
상용구들만 포함하고 있다.
hostAliases를 사용하여 추가 항목들 추가하기
기본 상용구 이외에, 추가 항목들을 hosts 파일에
추가할 수 있다.
예를 들어, foo.local, bar.local이 127.0.0.1로,
foo.remote, bar.remote가 10.1.2.3로 해석될 수 있도록, .spec.hostAliases 항목에서 정의하여 파드에
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"
다음을 실행하여 해당 구성으로 파드를 실행할 수 있다.
kubectl apply -f https://k8s.io/examples/service/networking/hostaliases-pod.yaml
pod/hostaliases-pod created
파드의 세부 정보를 검토하여 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 파일을 관리한다.
역사적으로, 쿠버네티스는 컨테이너 런타임으로 계속 도커 엔진을 사용해 왔으며,
각 컨테이너가 시작된 뒤에 도커 엔진이 /etc/hosts 파일을 수정할 수 있었다.
현재 쿠버네티스는 다양한 컨테이너 런타임을 사용할 수 있으며,
kubelet이 각 컨테이너 내의 hosts 파일을 관리하므로
어떤 컨테이너 런타임을 사용하는지에 상관없이 동일한 결과를 얻을 수 있다.
주의:
컨테이너 내부의 호스트 파일을 수동으로 변경하면 안된다.
호스트 파일을 수동으로 변경하면, 컨테이너가 종료되면 변경 사항이 손실된다.
2 - IPv4/IPv6 이중 스택 검증
이 문서는 IPv4/IPv6 이중 스택이 활성화된 쿠버네티스 클러스터들을 어떻게 검증하는지 설명한다.
시작하기 전에
- 이중 스택 네트워킹을 위한 제공자 지원 (클라우드 제공자 또는 기타 제공자들은 라우팅 가능한 IPv4/IPv6 네트워크 인터페이스를 제공하는 쿠버네티스 노드들을 제공해야 한다.)
- 이중 스택 네트워킹을 지원하는 네트워크 플러그인
- 이중 스택 활성화 클러스터
버전 확인을 위해서, 다음 커맨드를 실행  kubectl version.
참고:
v1.23 이전 버전에서도 검증을 수행할 수 있지만 GA 기능으로만 제공되며, v1.23부터 공식적으로 지원된다.어드레싱 검증
노드 어드레싱 검증
각각의 이중 스택 노드는 단일 IPv4 블록 및 단일 IPv6 블록을 할당받아야 한다. IPv4/IPv6 파드 주소 범위를 다음 커맨드를 실행하여 검증한다. 샘플 노드 이름을 클러스터 내 검증된 이중 스택 노드로 대체한다. 본 예제에서, 노드 이름은 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
파드 어드레싱 검증
파드가 IPv4 및 IPv6 주소를 할당받았는지 검증한다. 파드 이름을 클러스터에서 검증된 파드로 대체한다. 본 예제에서 파드 이름은 pod01 이다.
kubectl get pods pod01 -o go-template --template='{{range .status.podIPs}}{{printf "%s\n" .ip}}{{end}}'
10.244.1.4
2001:db8::4
status.podIPs fieldPath를 통한 다운워드(downward) API로 파드 IP들을 검증할 수도 있다. 다음 스니펫은 컨테이너 내 MY_POD_IPS 라는 환경 변수를 통해 파드 IP들을 어떻게 노출시킬 수 있는지 보여준다.
        env:
        - name: MY_POD_IPS
          valueFrom:
            fieldRef:
              fieldPath: status.podIPs
다음 커맨드는 컨테이너 내 MY_POD_IPS 환경 변수의 값을 출력한다. 해당 값은 파드의 IPv4 및 IPv6 주소를 나타내는 쉼표로 구분된 목록이다.
kubectl exec -it pod01 -- set | grep MY_POD_IPS
MY_POD_IPS=10.244.1.4,2001:db8::4
파드의 IP 주소는 또한 컨테이너 내 /etc/hosts 에 적힐 것이다. 다음 커맨드는 이중 스택 파드의 /etc/hosts 에 cat을 실행시킨다. 출력 값을 통해 파드의 IPv4 및 IPv6 주소 모두 검증할 수 있다.
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
서비스 검증
.spec.ipFamilyPolicy 를 명시적으로 정의하지 않은 다음의 서비스를 생성한다. 쿠버네티스는 처음 구성된 service-cluster-ip-range 에서 서비스에 대한 클러스터 IP를 할당하고 .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을 확인한다.
kubectl get svc my-service -o yaml
이 서비스에서 .spec.ipFamilyPolicy 를 SingleStack 으로 설정하고 .spec.clusterIP 를 kube-controller-manager의 --service-cluster-ip-range 플래그를 통해 설정된 첫 번째 구성 범위에서 IPv4 주소로 설정한다.
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: {}
.spec.ipFamilies 의 첫 번째 배열 요소로 IPv6 을 명시적으로 정의하는 다음 서비스를 생성한다. Kubernetes는 service-cluster-ip-range로 구성된 IPv6 범위에서 서비스용 클러스터 IP를 할당하고 .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을 확인한다.
kubectl get svc my-service -o yaml
이 서비스에서 .spec.ipFamilyPolicy 를 SingleStack 으로 설정하고 .spec.clusterIP 를 kube-controller-manager의 --service-cluster-ip-range 플래그를 통해 설정된 IPv6 범위에서 IPv6 주소로 설정한다.
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: {}
PreferDualStack 에 .spec.ipFamilyPolicy 을 명시적으로 정의하는 다음 서비스를 생성한다. 쿠버네티스는 IPv4 및 IPv6 주소를 모두 할당하고 (이 클러스터에는 이중 스택을 사용하도록 설정되었으므로) .spec.ipFamilies 배열에 있는 첫 번째 요소의 주소 계열을 기반으로.spec.ClusterIP 목록에서 .spec.ClusterIPs 를 선택한다.
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
참고:
kubectl get svc 명령어는 오직 CLUSTER-IP 필드에 주요 IP만 표시한다.
 kubectl get svc -l app.kubernetes.io/name: MyApp
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-service   ClusterIP   10.0.216.242   <none>        80/TCP    5s
서비스가 kubectl describe 를 사용하여 IPv4 및 IPv6 주소 블록에서 클러스터 IP를 가져오는지 확인한다. 그런 다음 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>
이중 스택 로드 밸런싱 서비스 생성
만약 클라우드 제공자가 IPv6 기반 외부 로드 밸런서 구성을 지원한다면 .spec.ipFamilyPolicy 의 PreferDualStack 과 .spec.ipFamilies 배열의 첫 번째 요소로 IPv6 및 LoadBalancer 로 설정된 type 필드를 사용하여 다음 서비스를 생성한다.
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
Check the Service:
kubectl get svc -l app.kubernetes.io/name: MyApp
서비스가 IPv6 주소 블록에서 CLUSTER-IP 주소 및 EXTERNAL-IP 주소를 할당받는지 검증한다. 그리고 나서 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