1 - एप्लिकेशन को सेवाओं से जोड़ें

कंटेनरों को जोड़ने के लिए कुबेरनेट्स मॉडल

अब चूंकि आपके पास लगातार चलने वाला, रेप्लिकेटेड एप्लीकेशन है, तो आप इसे नेटवर्क पर प्रदर्शित कर सकते हैं।

Kubernetes मानता है कि पॉड अन्य पॉड के साथ संवाद कर सकते हैं, चाहे वे किसी भी होस्ट पर उतरें। Kubernetes हर पॉड को अपना क्लस्टर-निजी IP पता देता है, इसलिए आपको पॉड के बीच स्पष्ट रूप से लिंक बनाने या कंटेनर पोर्ट को होस्ट पोर्ट पर मैप करने की आवश्यकता नहीं है। इसका मतलब है कि पॉड के भीतर सभी कंटेनर लोकलहोस्ट पर एक-दूसरे के पोर्ट तक पहुँच सकते हैं, और क्लस्टर में सभी पॉड NAT के बिना एक-दूसरे को देख सकते हैं। इस दस्तावेज़ का बाकी हिस्सा इस बात पर विस्तार से बताता है कि आप इस तरह के नेटवर्किंग मॉडल पर विश्वसनीय सेवाएँ कैसे चला सकते हैं।

यह ट्यूटोरियल अवधारणा को प्रदर्शित करने के लिए एक सरल nginx वेब सर्वर का उपयोग करता है।

पॉड्स को क्लस्टर के सामने लाना

हमने पिछले उदाहरण में ऐसा किया था, लेकिन आइए इसे एक बार फिर से करें और नेटवर्किंग परिप्रेक्ष्य पर ध्यान केंद्रित करें। एक nginx पॉड बनाएँ, और ध्यान दें कि इसमें एक कंटेनर पोर्ट विनिर्देश है:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

इससे यह आपके क्लस्टर के किसी भी नोड से एक्सेस करने योग्य हो जाता है। पॉड जिस नोड पर चल रहा है, उसे जांचें:

kubectl apply -f ./run-my-nginx.yaml
kubectl get pods -l run=my-nginx -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP            NODE
my-nginx-3800858182-jr4a2   1/1       Running   0          13s       10.244.3.4    kubernetes-minion-905m
my-nginx-3800858182-kna2y   1/1       Running   0          13s       10.244.2.5    kubernetes-minion-ljyd

अपने पॉड्स के IP की जाँच करें:

kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs
    POD_IP
    [map[ip:10.244.3.4]]
    [map[ip:10.244.2.5]]

आपको अपने क्लस्टर में किसी भी नोड में ssh करने में सक्षम होना चाहिए और दोनों IP के विरुद्ध क्वेरी बनाने के लिए curl जैसे टूल का उपयोग करना चाहिए। ध्यान दें कि कंटेनर नोड पर पोर्ट 80 का उपयोग नहीं कर रहे हैं, न ही ट्रैफ़िक को पॉड में रूट करने के लिए कोई विशेष NAT नियम हैं। इसका मतलब है कि आप एक ही नोड पर एक ही containerPort का उपयोग करके कई nginx पॉड चला सकते हैं, और पॉड के लिए निर्दिष्ट IP पते का उपयोग करके अपने क्लस्टर में किसी भी अन्य पॉड या नोड से उन्हें एक्सेस कर सकते हैं। यदि आप होस्ट नोड पर किसी विशिष्ट पोर्ट को बैकिंग पॉड्स पर अग्रेषित करने की व्यवस्था करना चाहते हैं, तो आप कर सकते हैं - लेकिन नेटवर्किंग मॉडल का मतलब यह होना चाहिए कि आपको ऐसा करने की आवश्यकता नहीं है।

यदि आप उत्सुक हैं तो आप कुबेरनेट्स नेटवर्किंग मॉडल के बारे में अधिक पढ़ सकते हैं।

सेवा बनाना

तो हमारे पास फ्लैट, क्लस्टर वाइड, एड्रेस स्पेस में nginx चलाने वाले पॉड्स हैं। सिद्धांत रूप में, आप इन पॉड्स से सीधे बात कर सकते हैं, लेकिन जब कोई नोड समाप्त हो जाता है तो क्या होता है? पॉड्स इसके साथ समाप्त हो जाते हैं, और डिप्लॉयमेंट के अंदर रेप्लिकासेट अलग-अलग आईपी के साथ नए पॉड्स बनाएगा। यह वह समस्या है जिसे सर्विस हल करती है।

कुबेरनेट्स सेवा एक अमूर्तता है जो आपके क्लस्टर में कहीं चल रहे पॉड्स के तार्किक सेट को परिभाषित करती है, जो सभी एक ही कार्यक्षमता प्रदान करते हैं। बनाए जाने पर, प्रत्येक सेवा को एक अद्वितीय IP पता (जिसे क्लस्टरIP भी कहा जाता है) सौंपा जाता है। यह पता सेवा के जीवनकाल से जुड़ा होता है, और सेवा के जीवित रहने के दौरान इसमें कोई बदलाव नहीं होगा। पॉड्स को सेवा से बात करने के लिए कॉन्फ़िगर किया जा सकता है, और यह जान सकते हैं कि सेवा के लिए संचार स्वचालित रूप से कुछ पॉड पर लोड-बैलेंस हो जाएगा जो सेवा का सदस्य है।

आप kubectl expose के साथ अपने 2 nginx प्रतिकृतियों के लिए एक सेवा बना सकते हैं:

kubectl expose deployment/my-nginx
service/my-nginx exposed

यह निम्न yaml kubectl apply -f के समतुल्य है:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx

यह विनिर्देश एक ऐसी सेवा बनाएगा जो run: my-nginx लेबल वाले किसी भी पॉड पर TCP पोर्ट 80 को लक्षित करेगी, और इसे एक अमूर्त सेवा पोर्ट पर प्रदर्शित करेगी। (targetPort: वह पोर्ट है जिस पर कंटेनर ट्रैफ़िक स्वीकार करता है, port: अमूर्त सेवा पोर्ट है, जो कोई भी पोर्ट हो सकता है जिसका उपयोग अन्य पॉड सेवा तक पहुंचने के लिए करते हैं)।

सेवा परिभाषा में समर्थित फ़ील्ड की सूची देखने के लिए ServiceAPI ऑब्जेक्ट देखें।

अपनी सेवा जांचें:

kubectl get svc my-nginx
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.0.162.149   <none>        80/TCP    21s

जैसा कि पहले बताया गया है, एक सेवा पॉड्स के एक समूह द्वारा समर्थित होती है। ये पॉड्स एंडपॉइंट-स्लाइस के माध्यम से उजागर होते हैं। सेवा के चयनकर्ता का लगातार मूल्यांकन किया जाएगा और परिणाम एक एंडपॉइंटस्लाइस पर पोस्ट किए जाएंगे जो लेबल का उपयोग करके सेवा से जुड़ा हुआ है। जब कोई पॉड समाप्त हो जाता है, तो उसे स्वचालित रूप से एंडपॉइंटस्लाइस से हटा दिया जाता है जिसमें इसे एंडपॉइंट के रूप में शामिल किया जाता है। सेवा के चयनकर्ता से मेल खाने वाले नए पॉड स्वचालित रूप से उस सेवा के लिए एंडपॉइंटस्लाइस में जुड़ जाएंगे।

एंडपॉइंट की जाँच करें, और ध्यान दें कि आईपी पहले वेरिएबलरण में बनाए गए पॉड के समान हैं:

kubectl describe svc my-nginx
Name:                my-nginx
Namespace:           default
Labels:              run=my-nginx
Annotations:         <none>
Selector:            run=my-nginx
Type:                ClusterIP
IP Family Policy:    SingleStack
IP Families:         IPv4
IP:                  10.0.162.149
IPs:                 10.0.162.149
Port:                <unset> 80/TCP
TargetPort:          80/TCP
Endpoints:           10.244.2.5:80,10.244.3.4:80
Session Affinity:    None
Events:              <none>
kubectl get endpointslices -l kubernetes.io/service-name=my-nginx
NAME             ADDRESSTYPE   PORTS   ENDPOINTS               AGE
my-nginx-7vzhx   IPv4          80      10.244.2.5,10.244.3.4   21s

अब आप अपने क्लस्टर में किसी भी नोड से <CLUSTER-IP>:<PORT> पर nginx सेवा को कर्ल करने में सक्षम होंगे। ध्यान दें कि सेवा IP पूरी तरह से वर्चुअल है, यह कभी भी वायर से नहीं टकराती है। यदि आप इस बारे में उत्सुक हैं कि यह कैसे काम करता है तो आप सेवा प्रॉक्सी के बारे में अधिक पढ़ सकते हैं।

सेवा तक पहुँचना

Kubernetes सर्विस खोजने के 2 प्राथमिक तरीकों का समर्थन करता है - पर्यावरण वेरिएबल और DNS। पहला तरीका बिना किसी परेशानी के काम करता है जबकि दूसरे के लिए CoreDNS क्लस्टर ऐडऑन की आवश्यकता होती है।

पर्यावरण वेरिएबल

जब कोई पॉड किसी नोड पर चलता है, तो क्यूबलेट प्रत्येक सक्रिय सेवा के लिए पर्यावरण वेरिएबल का एक सेट जोड़ता है। यह एक क्रम समस्या का परिचय देता है। इसका कारण जानने के लिए, अपने चल रहे nginx पॉड्स के पर्यावरण का निरीक्षण करें (आपका पॉड नाम अलग होगा):

kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443

ध्यान दें कि आपकी सेवा का कोई उल्लेख नहीं है। ऐसा इसलिए है क्योंकि आपने सेवा से पहले प्रतिकृतियां बनाई हैं। ऐसा करने का एक और नुकसान यह है कि शेड्यूलर दोनों पॉड को एक ही मशीन पर रख सकता है, जो आपकी पूरी सेवा को बंद कर देगा यदि यह समाप्त हो जाती है। हम 2 पॉड को समाप्त कर और उन्हें फिर से बनाने के लिए परिनियोजन की प्रतीक्षा करके इसे सही तरीके से कर सकते हैं। इस बार सेवा प्रतिकृतियों से पहले मौजूद है। यह आपको अपने पॉड के शेड्यूलर-स्तर की सेवा प्रसार देगा (बशर्ते आपके सभी नोड्स की क्षमता समान हो), साथ ही साथ सही पर्यावरण वेरिएबल:

kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;

kubectl get pods -l run=my-nginx -o wide
NAME                        READY     STATUS    RESTARTS   AGE     IP            NODE
my-nginx-3800858182-e9ihh   1/1       Running   0          5s      10.244.2.7    kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4   1/1       Running   0          5s      10.244.3.8    kubernetes-minion-905m

आप देखेंगे कि पॉड्स के अलग-अलग नाम हैं, क्योंकि उन्हें समाप्त कर दिया जाता है और फिर से बनाया जाता है।

kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
MY_NGINX_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT_HTTPS=443

डीएनएस

Kubernetes एक DNS क्लस्टर ऐडऑन सेवा प्रदान करता है जो स्वचालित रूप से अन्य सेवाओं को DNS नाम प्रदान करता है। आप जाँच सकते हैं कि यह आपके क्लस्टर पर चल रहा है या नहीं:

kubectl get services kube-dns --namespace=kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns   ClusterIP   10.0.0.10    <none>        53/UDP,53/TCP   8m

इस खंड का बाकी हिस्सा यह मान लेगा कि आपके पास एक लंबे समय तक चलने वाली IP सेवा (my-nginx) है, और एक DNS सर्वर है जिसने उस IP को एक नाम दिया है। यहाँ हम CoreDNS क्लस्टर ऐडऑन (एप्लिकेशन नाम kube-dns) का उपयोग करते हैं, ताकि आप मानक विधियों (जैसे gethostbyname()) का उपयोग करके अपने क्लस्टर में किसी भी पॉड से सेवा से बात कर सकें। यदि CoreDNS नहीं चल रहा है, तो आप इसे CoreDNS README या CoreDNS इंस्टॉल करने का संदर्भ देकर सक्षम कर सकते हैं।

kubectl run curl --image=radial/busyboxplus:curl -i --tty --rm
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt

फिर, एंटर दबाएं और nslookup my-nginx चलाएं:

[ root@curl-131556218-9fnch:/ ]$ nslookup my-nginx
Server:    10.0.0.10
Address 1: 10.0.0.10

Name:      my-nginx
Address 1: 10.0.162.149

सेवा को सुरक्षित करना

अब तक हमने क्लस्टर के भीतर से ही nginx सर्वर को एक्सेस किया है। सेवा को इंटरनेट पर दिखाने से पहले, आप यह सुनिश्चित करना चाहते हैं कि संचार चैनल सुरक्षित है। इसके लिए, आपको निम्न की आवश्यकता होगी:

  • https के लिए स्व-हस्ताक्षरित प्रमाणपत्र (जब तक कि आपके पास पहले से कोई पहचान प्रमाणपत्र न हो)
  • प्रमाणपत्रों का उपयोग करने के लिए कॉन्फ़िगर किया गया एक nginx सर्वर
  • एक सीक्रेट जो प्रमाणपत्रों को पॉड्स के लिए सुलभ बनाता है

आप ये सब nginx https उदाहरण से प्राप्त कर सकते हैं। इसके लिए go and make tools इंस्टॉल करना आवश्यक है। यदि आप उन्हें इंस्टॉल नहीं करना चाहते हैं, तो बाद में मैन्युअल चरणों का पालन करें। संक्षेप में:

make keys KEY=/tmp/nginx.key CERT=/tmp/nginx.crt
kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
secret/nginxsecret created
kubectl get secrets
NAME                  TYPE                                  DATA      AGE
nginxsecret           kubernetes.io/tls                     2         1m

और कॉन्फ़िगरेशन मैप भी:

kubectl create configmap nginxconfigmap --from-file=default.conf

आप Kubernetes उदाहरण प्रोजेक्ट रेपो में default.conf के लिए उदाहरण पा सकते हैं।

configmap/nginxconfigmap created
kubectl get configmaps
NAME             DATA   AGE
nginxconfigmap   1      114s

आप निम्न कमांड का उपयोग करके nginxconfigmap ConfigMap का विवरण देख सकते हैं:

kubectl describe configmap  nginxconfigmap

इसका आउटपुट कुछ इस प्रकार है:

Name:         nginxconfigmap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
default.conf:
----
server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        listen 443 ssl;

        root /usr/share/nginx/html;
        index index.html;

        server_name localhost;
        ssl_certificate /etc/nginx/ssl/tls.crt;
        ssl_certificate_key /etc/nginx/ssl/tls.key;

        location / {
                try_files $uri $uri/ =404;
        }
}

BinaryData
====

Events:  <none>

यदि आपको make चलाने में समस्या आती है (उदाहरण के लिए विंडोज़ पर) तो निम्नलिखित मैनुअल चरणों का पालन करें:

# Create a public private key pair
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
# Convert the keys to base64 encoding
cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64

पिछले आदेशों से आउटपुट का उपयोग करके yaml फ़ाइल बनाएँ, जैसा कि नीचे दिया गया है। base64 एन्कोडेड मान सभी एक ही पंक्ति में होने चाहिए।

apiVersion: "v1"
kind: "Secret"
metadata:
  name: "nginxsecret"
  namespace: "default"
type: kubernetes.io/tls
data:
  tls.crt: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
  tls.key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"

अब निम्न फ़ाइल का उपयोग करके सीक्रेट्स बनाएं:

kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME                  TYPE                                  DATA      AGE
nginxsecret           kubernetes.io/tls                     2         1m

अब अपने nginx प्रतिकृतियों को संशोधित करें ताकि सीक्रेट् मे प्रमाण पत्र और सेवा का उपयोग करके एक https सर्वर शुरू किया जा सके, ताकि दोनों पोर्ट (80 और 443) उजागर हो सकें:

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    protocol: TCP
    name: https
  selector:
    run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 1
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      volumes:
      - name: secret-volume
        secret:
          secretName: nginxsecret
      - name: configmap-volume
        configMap:
          name: nginxconfigmap
      containers:
      - name: nginxhttps
        image: bprashanth/nginxhttps:1.0
        ports:
        - containerPort: 443
        - containerPort: 80
        volumeMounts:
        - mountPath: /etc/nginx/ssl
          name: secret-volume
        - mountPath: /etc/nginx/conf.d
          name: configmap-volume

Nginx-secure-app मैनिफ़ेस्ट के बारे में उल्लेखनीय बातें:

  • इसमें एक ही फ़ाइल में डिप्लॉयमेंट और सेवा विनिर्देश दोनों शामिल हैं।
  • nginx सर्वर पोर्ट 80 पर HTTP ट्रैफ़िक और 443 पर HTTPS ट्रैफ़िक प्रदान करता है, और nginx सेवा दोनों पोर्ट को उजागर करती है।
  • प्रत्येक कंटेनर को /etc/nginx/ssl पर माउंट किए गए वॉल्यूम के माध्यम से कुंजियों तक पहुंच प्राप्त होती है। इसे nginx सर्वर शुरू होने से पहले सेट किया जाता है।
kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml

इस बिंदु पर आप किसी भी नोड से nginx सर्वर तक पहुंच सकते हैं।

kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs
    POD_IP
    [map[ip:10.244.3.5]]
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>

ध्यान दें कि हमने अंतिम चरण में कर्ल को -k पैरामीटर कैसे दिया, ऐसा इसलिए है क्योंकि हम प्रमाणपत्र निर्माण के समय nginx चलाने वाले पॉड्स के बारे में कुछ नहीं जानते हैं, इसलिए हमें कर्ल को CName बेमेल को अनदेखा करने के लिए कहना होगा। एक सेवा बनाकर हमने प्रमाणपत्र में उपयोग किए गए CName को सेवा लुकअप के दौरान पॉड्स द्वारा उपयोग किए जाने वाले वास्तविक DNS नाम से जोड़ा। आइए इसे पॉड से परखें (सरलता के लिए उसी सीक्रेट का पुनः उपयोग किया जा रहा है, पॉड को सेवा तक पहुँचने के लिए केवल nginx.crt की आवश्यकता है):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: curl-deployment
spec:
  selector:
    matchLabels:
      app: curlpod
  replicas: 1
  template:
    metadata:
      labels:
        app: curlpod
    spec:
      volumes:
      - name: secret-volume
        secret:
          secretName: nginxsecret
      containers:
      - name: curlpod
        command:
        - sh
        - -c
        - while true; do sleep 1; done
        image: radial/busyboxplus:curl
        volumeMounts:
        - mountPath: /etc/nginx/ssl
          name: secret-volume
kubectl apply -f ./curlpod.yaml
kubectl get pods -l app=curlpod
NAME                               READY     STATUS    RESTARTS   AGE
curl-deployment-1515033274-1410r   1/1       Running   0          1m
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/tls.crt
...
<title>Welcome to nginx!</title>
...

सेवा को उजागर करना

अपने अनुप्रयोगों के कुछ हिस्सों के लिए आप किसी बाहरी IP पते पर सेवा प्रदर्शित करना चाह सकते हैं। Kubernetes ऐसा करने के दो तरीकों का समर्थन करता है: NodePorts और LoadBalancers। पिछले अनुभाग में बनाई गई सेवा पहले से ही NodePort का उपयोग करती है, इसलिए यदि आपके नोड में सार्वजनिक IP है, तो आपका nginx HTTPS प्रतिकृति इंटरनेट पर ट्रैफ़िक की सेवा के लिए तैयार है।

kubectl get svc my-nginx -o yaml | grep nodePort -C 5
  uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
  clusterIP: 10.0.162.149
  ports:
  - name: http
    nodePort: 31704
    port: 8080
    protocol: TCP
    targetPort: 80
  - name: https
    nodePort: 32453
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    run: my-nginx
kubectl get nodes -o yaml | grep ExternalIP -C 1
    - address: 104.197.41.11
      type: ExternalIP
    allocatable:
--
    - address: 23.251.152.56
      type: ExternalIP
    allocatable:
...

$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
...
<h1>Welcome to nginx!</h1>

आइए अब क्लाउड लोड बैलेंसर का उपयोग करने के लिए सेवा को फिर से बनाएँ। my-nginx सेवा के Type को NodePort से LoadBalancer में बदलें:

kubectl edit svc my-nginx
kubectl get svc my-nginx
NAME       TYPE           CLUSTER-IP     EXTERNAL-IP        PORT(S)               AGE
my-nginx   LoadBalancer   10.0.162.149     xx.xxx.xxx.xxx     8080:30163/TCP        21s
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>

EXTERNAL-IP कॉलम में IP पता वह है जो सार्वजनिक इंटरनेट पर उपलब्ध है।

CLUSTER-IP केवल आपके क्लस्टर/निजी क्लाउड नेटवर्क के अंदर उपलब्ध है।

ध्यान दें कि AWS पर, LoadBalancer टाइप करने पर एक ELB बनता है, जो IP का नहीं, बल्कि एक (लंबे) होस्टनाम का उपयोग करता है। यह मानक kubectl get svc आउटपुट में फ़िट होने के लिए बहुत लंबा है, इसलिए आपको इसे देखने के लिए kubectl description service my-nginx करना होगा। आपको कुछ इस तरह दिखाई देगा:

kubectl describe service my-nginx
...
LoadBalancer Ingress:   a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...

आगे क्या है

2 - स्रोत आईपी का उपयोग करें

Kubernetes क्लस्टर में चलने वाले एप्लिकेशन सर्विस एब्स्ट्रैक्शन के ज़रिए एक-दूसरे और बाहरी दुनिया से संपर्क करते हैं और उनसे संवाद करते हैं। यह दस्तावेज़ बताता है कि अलग-अलग तरह की सेवाओं को भेजे जाने वाले पैकेट के स्रोत IP का क्या होता है और आप अपनी ज़रूरतों के हिसाब से इस व्यवहार को कैसे बदल सकते हैं।

शुरू करने से पहले

शब्दावली

इस दस्तावेज़ में निम्नलिखित शब्दों का प्रयोग किया गया है:

NAT
नेटवर्क एड्रेस ट्रांसलेशन
Source NAT
पैकेट पर स्रोत आईपी को प्रतिस्थापित करना; इस पृष्ठ पर, इसका अर्थ आमतौर पर नोड के आईपी पते के साथ प्रतिस्थापित करना है।
Destination NAT
पैकेट पर गंतव्य आईपी को प्रतिस्थापित करना; इस पृष्ठ पर, इसका मतलब आमतौर पर पॉड के आईपी पते के साथ प्रतिस्थापित करना है
VIP
एक वर्चुअल आईपी पता, जैसे कि कुबेरनेट्स में प्रत्येक सेवा को निर्दिष्ट किया गया है
kube-proxy
एक नेटवर्क डेमॉन जो प्रत्येक नोड पर सेवा वीआईपी प्रबंधन को व्यवस्थित करता है

Prerequisites

आपको कुबरनेट्स क्लस्टर की ज़रूरत पड़ेगी और क्यूब सीटीएल कमांड लाइन साधन को समनुरूप करना होगा ताकि वो आपके क्लस्टर के साथ संवाद कर सकें। हमारी सलाह है की इस टुटोरिअल को क्लस्टर में रन करने के लिए कम से कम दो नोड का इस्तेमाल करे जो कि कंट्रोल प्लेन होस्ट के तरह ना एक्ट करे। अगर आपके पास पहले से क्लस्टर नही है, आप minikube की मदद से वह बना सकते है या आप नीचे दिए हुए इन दो कुबरनेट्स प्लेग्राउंड का इस्तेमाल कर सकते हैं:

उदाहरणों में एक छोटे nginx वेबसर्वर का उपयोग किया गया है जो HTTP हेडर के माध्यम से प्राप्त अनुरोधों के स्रोत IP को प्रतिध्वनित करता है। आप इसे निम्न प्रकार से बना सकते हैं:

kubectl create deployment source-ip-app --image=registry.k8s.io/echoserver:1.4

आउटपुट है:

deployment.apps/source-ip-app created

उद्देश्य

  • विभिन्न प्रकार की सेवाओं के माध्यम से एक सरल अनुप्रयोग को उजागर करें
  • समझें कि प्रत्येक सेवा प्रकार स्रोत IP NAT को कैसे संभालता है
  • स्रोत IP को संरक्षित करने में शामिल ट्रेडऑफ़ को समझें

Type=ClusterIP वाली सेवाओं के लिए स्रोत IP

यदि आप kube-proxy को iptables मोड (डिफ़ॉल्ट) में चला रहे हैं, तो क्लस्टर के भीतर से ClusterIP को भेजे गए पैकेट कभी भी स्रोत NAT'd नहीं होते हैं। आप kube-proxy मोड को उस नोड पर http://localhost:10249/proxyMode लाकर क्वेरी कर सकते हैं जहाँ kube-proxy चल रहा है।

kubectl get nodes

इसका आउटपुट कुछ इस प्रकार है:

NAME                           STATUS     ROLES    AGE     VERSION
kubernetes-node-6jst   Ready      <none>   2h      v1.13.0
kubernetes-node-cx31   Ready      <none>   2h      v1.13.0
kubernetes-node-jj1t   Ready      <none>   2h      v1.13.0

किसी एक नोड पर प्रॉक्सी मोड प्राप्त करें (kube-proxy पोर्ट 10249 पर सुनता है):

# Run this in a shell on the node you want to query.
curl http://localhost:10249/proxyMode

इसका आउटपुट कुछ इस प्रकार है:

iptables

आप स्रोत IP ऐप पर सेवा बनाकर स्रोत IP संरक्षण का परीक्षण कर सकते हैं:

kubectl expose deployment source-ip-app --name=clusterip --port=80 --target-port=8080

इसका आउटपुट कुछ इस प्रकार है:

service/clusterip exposed
kubectl get svc clusterip

इसका आउटपुट कुछ इस प्रकार है:

NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
clusterip    ClusterIP   10.0.170.92   <none>        80/TCP    51s

और उसी क्लस्टर में एक पॉड से ClusterIP को हिट करना:

kubectl run busybox -it --image=busybox:1.28 --restart=Never --rm

इसका आउटपुट कुछ इस प्रकार है:

Waiting for pod default/busybox to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.

फिर आप उस पॉड के अंदर एक कमांड चला सकते हैं:

# Run this inside the terminal from "kubectl run"
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue
    link/ether 0a:58:0a:f4:03:08 brd ff:ff:ff:ff:ff:ff
    inet 10.244.3.8/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::188a:84ff:feb0:26a5/64 scope link
       valid_lft forever preferred_lft forever

…फिर लोकल वेबसर्वर को क्वेरी करने के लिए wget का उपयोग करें

# Replace "10.0.170.92" with the IPv4 address of the Service named "clusterip"
wget -qO - 10.0.170.92
CLIENT VALUES:
client_address=10.244.3.8
command=GET
...

client_address हमेशा क्लाइंट पॉड का IP पता होता है, चाहे क्लाइंट पॉड और सर्वर पॉड एक ही नोड में हों या अलग-अलग नोड्स में हों।

Type=NodePort वाली सेवाओं के लिए स्रोत IP

Type=NodePort के साथ सेवाओं को भेजे गए पैकेट डिफ़ॉल्ट रूप से स्रोत NAT'd होते हैं। आप NodePort सेवा बनाकर इसका परीक्षण कर सकते हैं:

kubectl expose deployment source-ip-app --name=nodeport --port=80 --target-port=8080 --type=NodePort

इसका आउटपुट कुछ इस प्रकार है:

service/nodeport exposed
NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services nodeport)
NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')

यदि आप क्लाउड प्रोवाइडर पर चल रहे हैं, तो आपको ऊपर बताए गए nodes:nodeport के लिए फ़ायरवॉल-नियम खोलने की आवश्यकता हो सकती है। अब आप ऊपर आवंटित नोड पोर्ट के माध्यम से क्लस्टर के बाहर से सेवा तक पहुँचने का प्रयास कर सकते हैं।

for node in $NODES; do curl -s $node:$NODEPORT | grep -i client_address; done

इसका आउटपुट कुछ इस प्रकार है:

client_address=10.180.1.1
client_address=10.240.0.5
client_address=10.240.0.3

ध्यान दें कि ये सही क्लाइंट IP नहीं हैं, ये क्लस्टर के आंतरिक IP हैं। यह इस तरह काम करता है:

  • क्लाइंट पैकेट को node2:nodePort पर भेजता है
  • node2 पैकेट में मौजूद सोर्स IP एड्रेस (SNAT) को अपने IP एड्रेस से बदल देता है
  • node2 पैकेट पर मौजूद डेस्टिनेशन IP को पॉड IP से बदल देता है
  • पैकेट को नोड 1 और फिर एंडपॉइंट पर भेजा जाता है
  • पॉड का जवाब वापस नोड 2 पर भेजा जाता है
  • पॉड का जवाब वापस क्लाइंट को भेजा जाता है

दृश्यात्मक रूप से:

source IP nodeport figure 01

Figure. Source IP Type=NodePort using SNAT

इससे बचने के लिए, Kubernetes में क्लाइंट स्रोत IP को संरक्षित करने की सुविधा है। यदि आप service.spec.externalTrafficPolicy को Local मान पर सेट करते हैं, तो kube-proxy केवल स्थानीय एंडपॉइंट पर प्रॉक्सी अनुरोधों को प्रॉक्सी करता है, और ट्रैफ़िक को अन्य नोड्स पर अग्रेषित नहीं करता है। यह दृष्टिकोण मूल स्रोत IP पते को संरक्षित करता है। यदि कोई स्थानीय एंडपॉइंट नहीं हैं, तो नोड पर भेजे गए पैकेट ड्रॉप हो जाते हैं, इसलिए आप किसी भी पैकेट प्रोसेसिंग नियम में सही स्रोत-आईपी पर भरोसा कर सकते हैं, आप एक पैकेट लागू कर सकते हैं जो एंडपॉइंट तक पहुंचता है।

service.spec.externalTrafficPolicy फ़ील्ड को निम्न प्रकार से सेट करें:

kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'

इसका आउटपुट कुछ इस प्रकार है:

service/nodeport patched

अब, परीक्षण पुनः चलाएँ:

for node in $NODES; do curl --connect-timeout 1 -s $node:$NODEPORT | grep -i client_address; done

आउटपुट इस प्रकार है:

client_address=198.51.100.79

ध्यान दें कि आपको केवल एक उत्तर मिला है, सही क्लाइंट IP के साथ, उस नोड से जिस पर एंडपॉइंट पॉड चल रहा है।

यह कुछ इस तरह काम करता है:

  • क्लाइंट पैकेट को node2:nodePort पर भेजता है, जिसमें कोई एंडपॉइंट नहीं है
  • पैकेट को छोड़ दिया जाता है
  • क्लाइंट पैकेट को node1:nodePort पर भेजता है, जिसमें एंडपॉइंट हैं
  • node1 पैकेट को सही सोर्स IP वाले एंडपॉइंट पर रूट करता है

दृश्यात्मक रूप से:

source IP nodeport figure 02

Figure. Source IP Type=NodePort preserves client source IP address

Type=LoadBalancer वाली सेवाओं के लिए स्रोत IP

Type=LoadBalancer के साथ सेवाओं को भेजे गए पैकेट डिफ़ॉल्ट रूप से स्रोत NAT'd होते हैं, क्योंकि Ready स्थिति में सभी शेड्यूल करने योग्य Kubernetes नोड लोड-बैलेंस्ड ट्रैफ़िक के लिए पात्र होते हैं। इसलिए यदि पैकेट बिना किसी एंडपॉइंट के नोड पर पहुंचते हैं, तो सिस्टम इसे एक एंडपॉइंट वाले नोड पर प्रॉक्सी करता है, पैकेट पर स्रोत IP को नोड के IP से बदल देता है (जैसा कि पिछले अनुभाग में वर्णित है)।

आप लोड बैलेंसर के माध्यम से स्रोत-आईपी-ऐप को उजागर करके इसका परीक्षण कर सकते हैं:

kubectl expose deployment source-ip-app --name=loadbalancer --port=80 --target-port=8080 --type=LoadBalancer

आउटपुट इस प्रकार है::

service/loadbalancer exposed

सेवा के आईपी पते का प्रिंट आउट लें:

kubectl get svc loadbalancer

आउटपुट इस प्रकार है:

NAME           TYPE           CLUSTER-IP    EXTERNAL-IP       PORT(S)   AGE
loadbalancer   LoadBalancer   10.0.65.118   203.0.113.140     80/TCP    5m

इसके बाद, इस सेवा के बाहरी-आईपी को अनुरोध भेजें:

curl 203.0.113.140

आउटपुट इस प्रकार है:

CLIENT VALUES:
client_address=10.240.0.5
...

हालाँकि, यदि आप Google Kubernetes Engine/GCE पर चल रहे हैं, तो उसी service.spec.externalTrafficPolicy फ़ील्ड को Local पर सेट करने से सेवा समापन बिंदुओं के बिना नोड्स को जानबूझकर स्वास्थ्य जांच में विफल होने के कारण लोडबैलेंस्ड ट्रैफ़िक के लिए योग्य नोड्स की सूची से खुद को हटाने के लिए मजबूर होना पड़ता है।

दृश्यात्मक रूप से:

Source IP with externalTrafficPolicy

आप एनोटेशन सेट करके इसका परीक्षण कर सकते हैं:

kubectl patch svc loadbalancer -p '{"spec":{"externalTrafficPolicy":"Local"}}'

आपको तुरंत Kubernetes द्वारा आवंटित service.spec.healthCheckNodePort फ़ील्ड दिखाई देगी:

kubectl get svc loadbalancer -o yaml | grep -i healthCheckNodePort

आउटपुट इस प्रकार है:

healthCheckNodePort: 32122

service.spec.healthCheckNodePort फ़ील्ड /healthz पर स्वास्थ्य जाँच करने वाले प्रत्येक नोड पर एक पोर्ट की ओर इशारा करता है। आप इसका परीक्षण कर सकते हैं:

kubectl get pod -o wide -l app=source-ip-app

आउटपुट इस प्रकार है:

NAME                            READY     STATUS    RESTARTS   AGE       IP             NODE
source-ip-app-826191075-qehz4   1/1       Running   0          20h       10.180.1.136   kubernetes-node-6jst

विभिन्न नोड्स पर /healthz एंडपॉइंट लाने के लिए curl का उपयोग करें:

# Run this locally on a node you choose
curl localhost:32122/healthz
1 Service Endpoints found

किसी भिन्न नोड पर आपको भिन्न परिणाम मिल सकता है:

# Run this locally on a node you choose
curl localhost:32122/healthz
No Service Endpoints Found

कंट्रोल प्लेन पर चलने वाला एक कंट्रोलर क्लाउड लोड बैलेंसर को आवंटित करने के लिए जिम्मेदार होता है। वही कंट्रोलर प्रत्येक नोड पर इस पोर्ट/पथ की ओर इशारा करते हुए HTTP स्वास्थ्य जांच भी आवंटित करता है। स्वास्थ्य जांच में विफल होने के लिए एंडपॉइंट के बिना 2 नोड्स के लिए लगभग 10 सेकंड प्रतीक्षा करें, फिर लोड बैलेंसर के IPv4 पते को क्वेरी करने के लिए curl का उपयोग करें:

curl 203.0.113.140

आउटपुट इस प्रकार है:

CLIENT VALUES:
client_address=198.51.100.79
...

क्रॉस-प्लेटफ़ॉर्म समर्थन

केवल कुछ क्लाउड प्रदाता ही Type=LoadBalancer वाली सेवाओं के माध्यम से स्रोत IP संरक्षण के लिए समर्थन प्रदान करते हैं। आप जिस क्लाउड प्रदाता पर काम कर रहे हैं, वह कुछ अलग-अलग तरीकों से लोडबैलेंसर के लिए अनुरोध को पूरा कर सकता है:

  1. एक प्रॉक्सी के साथ जो क्लाइंट कनेक्शन को समाप्त करता है और आपके नोड्स/एंडपॉइंट्स के लिए एक नया कनेक्शन खोलता है। ऐसे मामलों में स्रोत IP हमेशा क्लाउड LB का होगा, क्लाइंट का नहीं।

  2. एक पैकेट फ़ॉरवर्डर के साथ, जैसे कि क्लाइंट से लोडबैलेंसर VIP को भेजे गए अनुरोध क्लाइंट के स्रोत IP वाले नोड पर समाप्त होते हैं, न कि किसी मध्यवर्ती प्रॉक्सी पर।

पहली श्रेणी के लोड बैलेंसर को लोडबैलेंसर और बैकएंड के बीच HTTP फॉरवर्डेड या X-FORWARDED-FOR हेडर या प्रॉक्सी प्रोटोकॉल जैसे वास्तविक क्लाइंट IP को संप्रेषित करने के लिए सहमत प्रोटोकॉल का उपयोग करना चाहिए। दूसरी श्रेणी के लोड बैलेंसर सेवा पर service.spec.healthCheckNodePort फ़ील्ड में संग्रहीत पोर्ट पर इंगित HTTP स्वास्थ्य जांच बनाकर ऊपर वर्णित सुविधा का लाभ उठा सकते हैं।

सफाई करना

सेवाएँ समाप्त करें:

kubectl delete svc -l app=source-ip-app

डिप्लॉयमेंट, रेप्लिका सेट और पॉड को समाप्त करें:

kubectl delete deployment source-ip-app

आगे क्या है

3 - पॉड्स और उनके एंडपॉइंट्स के लिए समाप्ति व्यवहार का अन्वेषण करें

एक बार जब आप अपने एप्लिकेशन को सेवा से कनेक्ट कर लेते हैं, तो एप्लिकेशन को सेवाओं से कनेक्ट करना में बताए गए चरणों का पालन करते हुए, आपके पास एक निरंतर चलने वाला, प्रतिकृति एप्लिकेशन होता है, जो नेटवर्क पर प्रदर्शित होता है। यह ट्यूटोरियल आपको पॉड्स के लिए समाप्ति प्रवाह को देखने और सुंदर कनेक्शन ड्रेनिंग को लागू करने के तरीकों का पता लगाने में मदद करता है।

पॉड्स और उनके एन्डपॉइन्ट्स के लिए समाप्ति प्रक्रिया

अक्सर ऐसे मामले होते हैं जब आपको पॉड को समाप्त करने की आवश्यकता होती है - चाहे वह अपग्रेड के लिए हो या स्केल डाउन के लिए। एप्लिकेशन की उपलब्धता में सुधार करने के लिए, उचित सक्रिय कनेक्शन ड्रेनिंग को लागू करना महत्वपूर्ण हो सकता है। यह ट्यूटोरियल अवधारणा को प्रदर्शित करने के लिए एक सरल nginx वेब सर्वर का उपयोग करके संगत एंडपॉइंट स्थिति और निष्कासन के संबंध में पॉड समाप्ति के प्रवाह की व्याख्या करता है।

Example flow with endpoint termination

निम्नलिखित उदाहरण पॉड्स की समाप्ति दस्तावेज़ में वर्णित प्रवाह है।

मान लीजिए कि आपके पास एक एकल nginx प्रतिकृति (केवल प्रदर्शन उद्देश्यों के लिए) और एक सेवा युक्त डिप्लॉयमेंट है:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      terminationGracePeriodSeconds: 120 # extra long grace period
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        lifecycle:
          preStop:
            exec:
              # Real life termination may take any time up to terminationGracePeriodSeconds.
              # In this example - just hang around for at least the duration of terminationGracePeriodSeconds,
              # at 120 seconds container will be forcibly terminated.
              # Note, all this time nginx will keep processing requests.
              command: [
                "/bin/sh", "-c", "sleep 180"
              ]
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

अब उपरोक्त फ़ाइलों का उपयोग करके डिप्लॉयमेंट पॉड और सेवा बनाएँ:

kubectl apply -f pod-with-graceful-termination.yaml
kubectl apply -f explore-graceful-termination-nginx.yaml

एक बार पॉड और सेवा चलने के बाद, आप किसी भी संबद्ध एंडपॉइंटस्लाइस का नाम प्राप्त कर सकते हैं:

kubectl get endpointslice

इसका आउटपुट कुछ इस प्रकार है:

NAME                  ADDRESSTYPE   PORTS   ENDPOINTS                 AGE
nginx-service-6tjbr   IPv4          80      10.12.1.199,10.12.1.201   22m

आप इसकी स्थिति देख सकते हैं, और पुष्टि कर सकते हैं कि एक एंडपॉइन्ट पंजीकृत है:

kubectl get endpointslices -o json -l kubernetes.io/service-name=nginx-service

इसका आउटपुट कुछ इस प्रकार है:

{
    "addressType": "IPv4",
    "apiVersion": "discovery.k8s.io/v1",
    "endpoints": [
        {
            "addresses": [
                "10.12.1.201"
            ],
            "conditions": {
                "ready": true,
                "serving": true,
                "terminating": false

अब आइए पॉड को समाप्त करें और सत्यापित करें कि पॉड को अनुग्रहपूर्ण समाप्ति अवधि (graceful termination period) कॉन्फ़िगरेशन का सम्मान करते हुए समाप्त किया जा रहा है:

kubectl delete pod nginx-deployment-7768647bf9-b4b9s

सभी पॉड्स की जानकारी प्राप्त करें:

kubectl get pods

इसका आउटपुट कुछ इस प्रकार है:

NAME                                READY   STATUS        RESTARTS      AGE
nginx-deployment-7768647bf9-b4b9s   1/1     Terminating   0             4m1s
nginx-deployment-7768647bf9-rkxlw   1/1     Running       0             8s

आप देख सकते हैं कि नया पॉड शेड्यूल हो गया है।

जब तक नए पॉड के लिए नया एंडपॉइंट बनाया जा रहा है, पुराना एंडपॉइंट अभी भी टर्मिनेटिंग अवस्था में है:

kubectl get endpointslice -o json nginx-service-6tjbr

इसका आउटपुट कुछ इस प्रकार है:

{
    "addressType": "IPv4",
    "apiVersion": "discovery.k8s.io/v1",
    "endpoints": [
        {
            "addresses": [
                "10.12.1.201"
            ],
            "conditions": {
                "ready": false,
                "serving": true,
                "terminating": true
            },
            "nodeName": "gke-main-default-pool-dca1511c-d17b",
            "targetRef": {
                "kind": "Pod",
                "name": "nginx-deployment-7768647bf9-b4b9s",
                "namespace": "default",
                "uid": "66fa831c-7eb2-407f-bd2c-f96dfe841478"
            },
            "zone": "us-central1-c"
        },
        {
            "addresses": [
                "10.12.1.202"
            ],
            "conditions": {
                "ready": true,
                "serving": true,
                "terminating": false
            },
            "nodeName": "gke-main-default-pool-dca1511c-d17b",
            "targetRef": {
                "kind": "Pod",
                "name": "nginx-deployment-7768647bf9-rkxlw",
                "namespace": "default",
                "uid": "722b1cbe-dcd7-4ed4-8928-4a4d0e2bbe35"
            },
            "zone": "us-central1-c"

इससे एप्लिकेशन को समाप्ति के दौरान अपनी स्थिति के बारे में बताने की अनुमति मिलती है और क्लाइंट (जैसे लोड बैलेंसर) को कनेक्शन ड्रेनिंग कार्यक्षमता को लागू करने की अनुमति मिलती है। ये क्लाइंट समाप्ति के समापन बिंदुओं का पता लगा सकते हैं और उनके लिए एक विशेष तर्क लागू कर सकते हैं।

Kubernetes में, समाप्त होने वाले एंडपॉइंट की ready स्थिति हमेशा false के रूप में सेट होती है। बैकवर्ड संगतता के लिए ऐसा होना ज़रूरी है, ताकि मौजूदा लोड बैलेंसर इसका इस्तेमाल नियमित ट्रैफ़िक के लिए न करें। अगर समाप्त होने वाले पॉड पर ट्रैफ़िक ड्रेनिंग की ज़रूरत है, तो वास्तविक तत्परता को सर्विंग की स्थिति के रूप में जाँचा जा सकता है।

जब पॉड समाप्त हो जाता है, तो पुराना एंडपॉइंट भी साथ ही साथ समाप्त हो जाएगा।

आगे क्या है