diff --git a/content/hi/docs/tutorials/services/_index.md b/content/hi/docs/tutorials/services/_index.md new file mode 100644 index 0000000000000..cd4811ccb8220 --- /dev/null +++ b/content/hi/docs/tutorials/services/_index.md @@ -0,0 +1,5 @@ +--- +title: सर्विसेज +weight: 70 +--- + diff --git a/content/hi/docs/tutorials/services/connect-applications-service.md b/content/hi/docs/tutorials/services/connect-applications-service.md new file mode 100644 index 0000000000000..11772f7f6dc7a --- /dev/null +++ b/content/hi/docs/tutorials/services/connect-applications-service.md @@ -0,0 +1,461 @@ +--- +title: एप्लिकेशन को सेवाओं से जोड़ें +content_type: tutorial +weight: 20 +--- + + + + +## कंटेनरों को जोड़ने के लिए कुबेरनेट्स मॉडल + +अब चूंकि आपके पास लगातार चलने वाला, रेप्लिकेटेड एप्लीकेशन है, तो आप इसे नेटवर्क पर प्रदर्शित कर सकते हैं। + +Kubernetes मानता है कि पॉड अन्य पॉड के साथ संवाद कर सकते हैं, चाहे वे किसी भी होस्ट पर उतरें। +Kubernetes हर पॉड को अपना क्लस्टर-निजी IP पता देता है, इसलिए आपको पॉड के बीच स्पष्ट रूप से लिंक बनाने या कंटेनर पोर्ट को होस्ट पोर्ट पर मैप करने की आवश्यकता नहीं है। इसका मतलब है कि पॉड के भीतर सभी कंटेनर लोकलहोस्ट पर एक-दूसरे के पोर्ट तक पहुँच सकते हैं, और क्लस्टर में सभी पॉड NAT के बिना एक-दूसरे को देख सकते हैं। इस दस्तावेज़ का बाकी हिस्सा इस बात पर विस्तार से बताता है कि आप इस तरह के नेटवर्किंग मॉडल पर विश्वसनीय सेवाएँ कैसे चला सकते हैं। + +यह ट्यूटोरियल अवधारणा को प्रदर्शित करने के लिए एक सरल nginx वेब सर्वर का उपयोग करता है। + + + +## पॉड्स को क्लस्टर के सामने लाना + +हमने पिछले उदाहरण में ऐसा किया था, लेकिन आइए इसे एक बार फिर से करें और नेटवर्किंग परिप्रेक्ष्य पर ध्यान केंद्रित करें। +एक nginx पॉड बनाएँ, और ध्यान दें कि इसमें एक कंटेनर पोर्ट विनिर्देश है: + +{{% code_sample file="service/networking/run-my-nginx.yaml" %}} + +इससे यह आपके क्लस्टर के किसी भी नोड से एक्सेस करने योग्य हो जाता है। पॉड जिस नोड पर चल रहा है, उसे जांचें: + +```shell +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 की जाँच करें: + +```shell +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 पते का उपयोग करके अपने क्लस्टर में किसी भी अन्य पॉड या नोड से उन्हें एक्सेस कर सकते हैं। यदि आप होस्ट नोड पर किसी विशिष्ट पोर्ट को बैकिंग पॉड्स पर अग्रेषित करने की व्यवस्था करना चाहते हैं, तो आप कर सकते हैं - लेकिन नेटवर्किंग मॉडल का मतलब यह होना चाहिए कि आपको ऐसा करने की आवश्यकता नहीं है। + +यदि आप उत्सुक हैं तो आप [कुबेरनेट्स नेटवर्किंग](/docs/concepts/cluster-administration/networking/#the-kubernetes-network-model) मॉडल के बारे में अधिक पढ़ सकते हैं। + +## सेवा बनाना + +तो हमारे पास फ्लैट, क्लस्टर वाइड, एड्रेस स्पेस में nginx चलाने वाले पॉड्स हैं। सिद्धांत रूप में, आप इन पॉड्स से सीधे बात कर सकते हैं, लेकिन जब कोई नोड समाप्त हो जाता है तो क्या होता है? पॉड्स इसके साथ समाप्त हो जाते हैं, और डिप्लॉयमेंट के अंदर रेप्लिकासेट अलग-अलग आईपी के साथ नए पॉड्स बनाएगा। यह वह समस्या है जिसे सर्विस हल करती है। + +कुबेरनेट्स सेवा एक अमूर्तता है जो आपके क्लस्टर में कहीं चल रहे पॉड्स के तार्किक सेट को परिभाषित करती है, जो सभी एक ही कार्यक्षमता प्रदान करते हैं। बनाए जाने पर, प्रत्येक सेवा को एक अद्वितीय IP पता (जिसे क्लस्टरIP भी कहा जाता है) सौंपा जाता है। यह पता सेवा के जीवनकाल से जुड़ा होता है, और सेवा के जीवित रहने के दौरान इसमें कोई बदलाव नहीं होगा। पॉड्स को सेवा से बात करने के लिए कॉन्फ़िगर किया जा सकता है, और यह जान सकते हैं कि सेवा के लिए संचार स्वचालित रूप से कुछ पॉड पर लोड-बैलेंस हो जाएगा जो सेवा का सदस्य है। + +आप `kubectl expose` के साथ अपने 2 nginx प्रतिकृतियों के लिए एक सेवा बना सकते हैं: + +```shell +kubectl expose deployment/my-nginx +``` +``` +service/my-nginx exposed +``` + +यह निम्न yaml `kubectl apply -f` के समतुल्य है: + +{{% code_sample file="service/networking/nginx-svc.yaml" %}} + +यह विनिर्देश एक ऐसी सेवा बनाएगा जो `run: my-nginx` लेबल वाले किसी भी पॉड पर TCP पोर्ट 80 को लक्षित करेगी, और इसे एक अमूर्त सेवा पोर्ट पर प्रदर्शित करेगी। (`targetPort`: वह पोर्ट है जिस पर कंटेनर ट्रैफ़िक स्वीकार करता है, `port`: अमूर्त सेवा पोर्ट है, जो कोई भी पोर्ट हो सकता है जिसका उपयोग अन्य पॉड सेवा तक पहुंचने के लिए करते हैं)। + +सेवा परिभाषा में समर्थित फ़ील्ड की सूची देखने के लिए [ServiceAPI](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core) ऑब्जेक्ट देखें। + +अपनी सेवा जांचें: + +```shell89 +kubectl get svc my-nginx +``` +``` +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +my-nginx ClusterIP 10.0.162.149 80/TCP 21s +``` + +जैसा कि पहले बताया गया है, एक सेवा पॉड्स के एक समूह द्वारा समर्थित होती है। ये पॉड्स +{{}} के माध्यम से उजागर होते हैं। +सेवा के चयनकर्ता का लगातार मूल्यांकन किया जाएगा और परिणाम एक एंडपॉइंटस्लाइस पर पोस्ट किए जाएंगे जो {{< glossary_tooltip term_id="label" text="लेबल">}} का उपयोग करके सेवा से जुड़ा हुआ है। +जब कोई पॉड समाप्त हो जाता है, तो उसे स्वचालित रूप से एंडपॉइंटस्लाइस से हटा दिया जाता है जिसमें इसे एंडपॉइंट के रूप में शामिल किया जाता है। सेवा के चयनकर्ता से मेल खाने वाले नए पॉड स्वचालित रूप से उस सेवा के लिए एंडपॉइंटस्लाइस में जुड़ जाएंगे। + +एंडपॉइंट की जाँच करें, और ध्यान दें कि आईपी पहले वेरिएबलरण में बनाए गए पॉड के समान हैं: + +```shell +kubectl describe svc my-nginx +``` +``` +Name: my-nginx +Namespace: default +Labels: run=my-nginx +Annotations: +Selector: run=my-nginx +Type: ClusterIP +IP Family Policy: SingleStack +IP Families: IPv4 +IP: 10.0.162.149 +IPs: 10.0.162.149 +Port: 80/TCP +TargetPort: 80/TCP +Endpoints: 10.244.2.5:80,10.244.3.4:80 +Session Affinity: None +Events: +``` +```shell +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 +``` + +अब आप अपने क्लस्टर में किसी भी नोड से `:` पर nginx सेवा को कर्ल करने में सक्षम होंगे। +ध्यान दें कि सेवा IP पूरी तरह से वर्चुअल है, यह कभी भी वायर से नहीं टकराती है। यदि आप इस बारे में उत्सुक हैं कि यह कैसे +काम करता है तो आप [सेवा प्रॉक्सी](/docs/reference/networking/virtual-ips/) के बारे में अधिक पढ़ सकते हैं। + + +## सेवा तक पहुँचना + +Kubernetes सर्विस खोजने के 2 प्राथमिक तरीकों का समर्थन करता है - पर्यावरण वेरिएबल और DNS। पहला तरीका बिना किसी +परेशानी के काम करता है जबकि दूसरे के लिए [CoreDNS]((https://releases.k8s.io/v{{< skew currentPatchVersion >}}/cluster/addons/dns/coredns)) क्लस्टर ऐडऑन की आवश्यकता होती है। + +{{< note >}} +यदि सेवा परिवेश वेरिएबल वांछित नहीं हैं (अपेक्षित प्रोग्राम वेरिएबलरों के साथ संभावित टकराव, प्रक्रिया के लिए बहुत अधिक वेरिएबल, केवल DNS का उपयोग, आदि के कारण) तो आप [पॉड स्पेक](/docs/reference/generated/kubernetes-api/v{{< skew latestVersion >}}/#pod-v1-core) पर `enableServiceLinks` ध्वज को `false` पर सेट करके इस मोड को अक्षम कर सकते हैं। +{{< /note >}} + + +### पर्यावरण वेरिएबल + +जब कोई पॉड किसी नोड पर चलता है, तो क्यूबलेट प्रत्येक सक्रिय सेवा के लिए पर्यावरण वेरिएबल का एक सेट जोड़ता है। यह एक क्रम समस्या का परिचय देता है। इसका कारण जानने के लिए, अपने चल रहे nginx पॉड्स के पर्यावरण का निरीक्षण करें (आपका पॉड नाम अलग होगा): + +```shell +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 पॉड को समाप्त कर और उन्हें फिर से बनाने के लिए परिनियोजन की प्रतीक्षा करके इसे सही तरीके से कर सकते हैं। इस बार सेवा प्रतिकृतियों से *पहले* मौजूद है। यह आपको अपने पॉड के शेड्यूलर-स्तर की सेवा प्रसार देगा (बशर्ते आपके सभी नोड्स की क्षमता समान हो), साथ ही साथ सही पर्यावरण वेरिएबल: + +```shell +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 +``` + +आप देखेंगे कि पॉड्स के अलग-अलग नाम हैं, क्योंकि उन्हें समाप्त कर दिया जाता है और फिर से बनाया जाता है। + +```shell +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 नाम प्रदान करता है। आप जाँच सकते हैं कि यह आपके क्लस्टर पर चल रहा है या नहीं: + +```shell +kubectl get services kube-dns --namespace=kube-system +``` +``` +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +kube-dns ClusterIP 10.0.0.10 53/UDP,53/TCP 8m +``` + +इस खंड का बाकी हिस्सा यह मान लेगा कि आपके पास एक लंबे समय तक चलने वाली IP सेवा (my-nginx) है, +और एक DNS सर्वर है जिसने उस IP को एक नाम दिया है। यहाँ हम CoreDNS क्लस्टर ऐडऑन (एप्लिकेशन नाम `kube-dns`) +का उपयोग करते हैं, ताकि आप मानक विधियों (जैसे `gethostbyname()`) का उपयोग करके अपने क्लस्टर में किसी भी पॉड से सेवा +से बात कर सकें। +यदि CoreDNS नहीं चल रहा है, तो आप इसे [CoreDNS README](https://github.com/coredns/deployment/tree/master/kubernetes) +या [CoreDNS इंस्टॉल](/docs/tasks/administer-cluster/coredns/#installing-coredns) करने का संदर्भ देकर सक्षम कर सकते हैं। + +```shell +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` चलाएं: + +```shell +[ 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 सर्वर +* एक [सीक्रेट](/docs/concepts/configuration/secret/) जो प्रमाणपत्रों को पॉड्स के लिए सुलभ बनाता है + +आप ये सब [nginx https उदाहरण](https://github.com/kubernetes/examples/tree/master/staging/https-nginx/) +से प्राप्त कर सकते हैं। +इसके लिए go and make tools इंस्टॉल करना आवश्यक है। यदि आप उन्हें इंस्टॉल नहीं करना चाहते हैं, तो बाद में मैन्युअल चरणों का पालन करें। संक्षेप में: + +```shell +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 +``` +```shell +kubectl get secrets +``` +``` +NAME TYPE DATA AGE +nginxsecret kubernetes.io/tls 2 1m +``` +और कॉन्फ़िगरेशन मैप भी: +```shell +kubectl create configmap nginxconfigmap --from-file=default.conf +``` + +आप [Kubernetes उदाहरण प्रोजेक्ट रेपो](https://github.com/kubernetes/examples/tree/bc9ca4ca32bb28762ef216386934bef20f1f9930/staging/https-nginx/) में `default.conf` के लिए उदाहरण पा सकते हैं। + +``` +configmap/nginxconfigmap created +``` +```shell +kubectl get configmaps +``` +``` +NAME DATA AGE +nginxconfigmap 1 114s +``` + +आप निम्न कमांड का उपयोग करके `nginxconfigmap` ConfigMap का विवरण देख सकते हैं: + +```shell +kubectl describe configmap nginxconfigmap +``` + +इसका आउटपुट कुछ इस प्रकार है: + +```console +Name: nginxconfigmap +Namespace: default +Labels: +Annotations: + +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: +``` + +यदि आपको make चलाने में समस्या आती है (उदाहरण के लिए विंडोज़ पर) तो निम्नलिखित मैनुअल चरणों का पालन करें: + +```shell +# 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 एन्कोडेड मान सभी एक ही पंक्ति में होने चाहिए। + +```yaml +apiVersion: "v1" +kind: "Secret" +metadata: + name: "nginxsecret" + namespace: "default" +type: kubernetes.io/tls +data: + tls.crt: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" + tls.key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K" +``` +अब निम्न फ़ाइल का उपयोग करके सीक्रेट्स बनाएं: + +```shell +kubectl apply -f nginxsecrets.yaml +kubectl get secrets +``` +``` +NAME TYPE DATA AGE +nginxsecret kubernetes.io/tls 2 1m +``` + +अब अपने nginx प्रतिकृतियों को संशोधित करें ताकि सीक्रेट् मे प्रमाण पत्र और सेवा का उपयोग करके एक https सर्वर शुरू किया जा सके, ताकि दोनों पोर्ट (80 और 443) उजागर हो सकें: + +{{% code_sample file="service/networking/nginx-secure-app.yaml" %}} + +Nginx-secure-app मैनिफ़ेस्ट के बारे में उल्लेखनीय बातें: + +- इसमें एक ही फ़ाइल में डिप्लॉयमेंट और सेवा विनिर्देश दोनों शामिल हैं। +- [nginx सर्वर](https://github.com/kubernetes/examples/tree/master/staging/https-nginx/default.conf) +पोर्ट 80 पर HTTP ट्रैफ़िक और 443 पर HTTPS ट्रैफ़िक प्रदान करता है, और nginx सेवा दोनों पोर्ट को उजागर करती है। +- प्रत्येक कंटेनर को `/etc/nginx/ssl` पर माउंट किए गए वॉल्यूम के माध्यम से कुंजियों तक पहुंच प्राप्त होती है। इसे nginx सर्वर शुरू होने से पहले सेट किया जाता है। + +```shell +kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml +``` + +इस बिंदु पर आप किसी भी नोड से nginx सर्वर तक पहुंच सकते हैं। + +```shell +kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs + POD_IP + [map[ip:10.244.3.5]] +``` + +```shell +node $ curl -k https://10.244.3.5 +... +

Welcome to nginx!

+``` + +ध्यान दें कि हमने अंतिम चरण में कर्ल को `-k` पैरामीटर कैसे दिया, ऐसा इसलिए है क्योंकि हम प्रमाणपत्र निर्माण के समय nginx चलाने वाले पॉड्स के बारे में कुछ नहीं जानते हैं, इसलिए हमें कर्ल को CName बेमेल को अनदेखा करने के लिए कहना होगा। एक सेवा बनाकर हमने प्रमाणपत्र में उपयोग किए गए CName को सेवा लुकअप के दौरान पॉड्स द्वारा उपयोग किए जाने वाले वास्तविक DNS नाम से जोड़ा। आइए इसे पॉड से परखें (सरलता के लिए उसी सीक्रेट का पुनः उपयोग किया जा रहा है, पॉड को सेवा तक पहुँचने के लिए केवल nginx.crt की आवश्यकता है): + +{{% code_sample file="service/networking/curlpod.yaml" %}} + +```shell +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 +``` +```shell +kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/tls.crt +... +Welcome to nginx! +... +``` + +## सेवा को उजागर करना + +अपने अनुप्रयोगों के कुछ हिस्सों के लिए आप किसी बाहरी IP पते पर सेवा प्रदर्शित करना चाह सकते हैं। +Kubernetes ऐसा करने के दो तरीकों का समर्थन करता है: NodePorts और LoadBalancers। पिछले अनुभाग में +बनाई गई सेवा पहले से ही `NodePort` का उपयोग करती है, इसलिए यदि आपके नोड में सार्वजनिक IP है, तो +आपका nginx HTTPS प्रतिकृति इंटरनेट पर ट्रैफ़िक की सेवा के लिए तैयार है। + +```shell +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 +``` +```shell +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://: -k +... +

Welcome to nginx!

+``` + +आइए अब क्लाउड लोड बैलेंसर का उपयोग करने के लिए सेवा को फिर से बनाएँ। +`my-nginx` सेवा के `Type` को `NodePort` से `LoadBalancer` में बदलें: + +```shell +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:// -k +... +Welcome to nginx! +``` + +`EXTERNAL-IP` कॉलम में IP पता वह है जो सार्वजनिक इंटरनेट पर उपलब्ध है। + +`CLUSTER-IP` केवल आपके क्लस्टर/निजी क्लाउड नेटवर्क के अंदर उपलब्ध है। + +ध्यान दें कि AWS पर, `LoadBalancer` टाइप करने पर एक ELB बनता है, जो IP का नहीं, बल्कि एक (लंबे) होस्टनाम का उपयोग करता है। यह मानक `kubectl get svc` आउटपुट में फ़िट होने के लिए बहुत लंबा है, इसलिए आपको इसे देखने के लिए `kubectl description service my-nginx` करना होगा। आपको कुछ इस तरह दिखाई देगा: + +```shell +kubectl describe service my-nginx +... +LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com +... +``` + + + +## {{% heading "whatsnext" %}} + + +* [क्लस्टर में किसी एप्लिकेशन तक पहुंचने के लिए सेवा का उपयोग](/docs/tasks/access-application-cluster/service-access-application-cluster/) के बारे में अधिक जानें +* [सेवा का उपयोग करके फ्रंट एंड को बैक एंड से कनेक्ट करने](/docs/tasks/access-application-cluster/connecting-frontend-backend/) के बारे में अधिक जानें +* [बाहरी लोड बैलेंसर बनाने](/docs/tasks/access-application-cluster/create-external-load-balancer/) के बारे में अधिक जानें diff --git a/content/hi/docs/tutorials/services/pods-and-endpoint-termination-flow.md b/content/hi/docs/tutorials/services/pods-and-endpoint-termination-flow.md new file mode 100644 index 0000000000000..b2bee28862ba6 --- /dev/null +++ b/content/hi/docs/tutorials/services/pods-and-endpoint-termination-flow.md @@ -0,0 +1,166 @@ +--- +title: पॉड्स और उनके एंडपॉइंट्स के लिए समाप्ति व्यवहार का अन्वेषण करें +content_type: tutorial +weight: 60 +--- + + + + +एक बार जब आप अपने एप्लिकेशन को सेवा से कनेक्ट कर लेते हैं, तो [एप्लिकेशन को सेवाओं से कनेक्ट करना](/hi/docs/tutorials/services/connect-applications-service/) में बताए गए चरणों का पालन करते हुए, आपके पास एक निरंतर चलने वाला, प्रतिकृति एप्लिकेशन होता है, जो नेटवर्क पर प्रदर्शित होता है। यह ट्यूटोरियल आपको पॉड्स के लिए समाप्ति प्रवाह को देखने और सुंदर कनेक्शन ड्रेनिंग को लागू करने के तरीकों का पता लगाने में मदद करता है। + + + + +## पॉड्स और उनके एन्डपॉइन्ट्स के लिए समाप्ति प्रक्रिया + +अक्सर ऐसे मामले होते हैं जब आपको पॉड को समाप्त करने की आवश्यकता होती है - चाहे वह अपग्रेड के लिए हो या स्केल डाउन के लिए। +एप्लिकेशन की उपलब्धता में सुधार करने के लिए, उचित सक्रिय कनेक्शन ड्रेनिंग को लागू करना महत्वपूर्ण हो सकता है। +यह ट्यूटोरियल अवधारणा को प्रदर्शित करने के लिए एक सरल nginx वेब सर्वर का उपयोग करके संगत एंडपॉइंट स्थिति और निष्कासन के संबंध में पॉड समाप्ति के प्रवाह की व्याख्या करता है। + + + +## Example flow with endpoint termination + +निम्नलिखित उदाहरण [पॉड्स की समाप्ति](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination) दस्तावेज़ में वर्णित प्रवाह है। + +मान लीजिए कि आपके पास एक एकल `nginx` प्रतिकृति (केवल प्रदर्शन उद्देश्यों के लिए) और एक सेवा युक्त डिप्लॉयमेंट है: + +{{% code_sample file="service/pod-with-graceful-termination.yaml" %}} + +{{% code_sample file="service/explore-graceful-termination-nginx.yaml" %}} + +अब उपरोक्त फ़ाइलों का उपयोग करके डिप्लॉयमेंट पॉड और सेवा बनाएँ: + +```shell +kubectl apply -f pod-with-graceful-termination.yaml +kubectl apply -f explore-graceful-termination-nginx.yaml +``` + +एक बार पॉड और सेवा चलने के बाद, आप किसी भी संबद्ध एंडपॉइंटस्लाइस का नाम प्राप्त कर सकते हैं: + +```shell +kubectl get endpointslice +``` + +इसका आउटपुट कुछ इस प्रकार है: + +```none +NAME ADDRESSTYPE PORTS ENDPOINTS AGE +nginx-service-6tjbr IPv4 80 10.12.1.199,10.12.1.201 22m +``` + +आप इसकी स्थिति देख सकते हैं, और पुष्टि कर सकते हैं कि एक एंडपॉइन्ट पंजीकृत है: + +```shell +kubectl get endpointslices -o json -l kubernetes.io/service-name=nginx-service +``` + +इसका आउटपुट कुछ इस प्रकार है: + +```none +{ + "addressType": "IPv4", + "apiVersion": "discovery.k8s.io/v1", + "endpoints": [ + { + "addresses": [ + "10.12.1.201" + ], + "conditions": { + "ready": true, + "serving": true, + "terminating": false +``` + +अब आइए पॉड को समाप्त करें और सत्यापित करें कि पॉड को अनुग्रहपूर्ण समाप्ति अवधि (graceful termination period) +कॉन्फ़िगरेशन का सम्मान करते हुए समाप्त किया जा रहा है: + +```shell +kubectl delete pod nginx-deployment-7768647bf9-b4b9s +``` + +सभी पॉड्स की जानकारी प्राप्त करें: + +```shell +kubectl get pods +``` + +इसका आउटपुट कुछ इस प्रकार है: + +```none +NAME READY STATUS RESTARTS AGE +nginx-deployment-7768647bf9-b4b9s 1/1 Terminating 0 4m1s +nginx-deployment-7768647bf9-rkxlw 1/1 Running 0 8s +``` + +आप देख सकते हैं कि नया पॉड शेड्यूल हो गया है। + +जब तक नए पॉड के लिए नया एंडपॉइंट बनाया जा रहा है, पुराना एंडपॉइंट अभी भी टर्मिनेटिंग अवस्था में है: + +```shell +kubectl get endpointslice -o json nginx-service-6tjbr +``` + +इसका आउटपुट कुछ इस प्रकार है: + +```none +{ + "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` के रूप में सेट होती है। +बैकवर्ड संगतता के लिए ऐसा होना ज़रूरी है, ताकि मौजूदा लोड बैलेंसर इसका इस्तेमाल नियमित ट्रैफ़िक के लिए न करें। अगर समाप्त होने वाले पॉड पर ट्रैफ़िक ड्रेनिंग की ज़रूरत है, तो वास्तविक तत्परता को `सर्विंग` की स्थिति के रूप में जाँचा जा सकता है। + +जब पॉड समाप्त हो जाता है, तो पुराना एंडपॉइंट भी साथ ही साथ समाप्त हो जाएगा। + + +## {{% heading "whatsnext" %}} + + +* जानें कि [एप्लिकेशन को सेवाओं से कैसे कनेक्ट करें](/docs/tutorials/services/connect-applications-service/) +* [क्लस्टर में किसी एप्लिकेशन तक पहुंचने के लिए सेवा का उपयोग करना](/docs/tasks/access-application-cluster/service-access-application-cluster/) के बारे में अधिक जानें +* [सेवा का उपयोग करके फ्रंट एंड को बैक एंड से कनेक्ट करना](/docs/tasks/access-application-cluster/connecting-frontend-backend/) के बारे में अधिक जानें +* [बाहरी लोड बैलेंसर बनाने](/docs/tasks/access-application-cluster/create-external-load-balancer/) के बारे में अधिक जानें + diff --git a/content/hi/docs/tutorials/services/source-ip.md b/content/hi/docs/tutorials/services/source-ip.md new file mode 100644 index 0000000000000..71fa7276ac0f8 --- /dev/null +++ b/content/hi/docs/tutorials/services/source-ip.md @@ -0,0 +1,417 @@ +--- +title: स्रोत आईपी का उपयोग करें +content_type: tutorial +min-kubernetes-server-version: v1.5 +weight: 40 +--- + + + +Kubernetes क्लस्टर में चलने वाले एप्लिकेशन सर्विस एब्स्ट्रैक्शन के ज़रिए एक-दूसरे और बाहरी दुनिया से संपर्क करते हैं और उनसे संवाद करते हैं। यह दस्तावेज़ बताता है कि अलग-अलग तरह की सेवाओं को भेजे जाने वाले पैकेट के स्रोत IP का क्या होता है और आप अपनी ज़रूरतों के हिसाब से इस व्यवहार को कैसे बदल सकते हैं। + + + +## {{% heading "prerequisites" %}} + + +### शब्दावली + +इस दस्तावेज़ में निम्नलिखित शब्दों का प्रयोग किया गया है: + +{{< comment >}} +यदि इस अनुभाग का स्थानीयकरण किया जा रहा है, तो लक्ष्य स्थानीयकरण के लिए समकक्ष विकिपीडिया पृष्ठों से लिंक करें। +{{< /comment >}} + +[NAT](https://en.wikipedia.org/wiki/Network_address_translation) +: नेटवर्क एड्रेस ट्रांसलेशन + +[Source NAT](https://en.wikipedia.org/wiki/Network_address_translation#SNAT) +: पैकेट पर स्रोत आईपी को प्रतिस्थापित करना; इस पृष्ठ पर, इसका अर्थ आमतौर पर नोड के आईपी पते के साथ प्रतिस्थापित करना है। + +[Destination NAT](https://en.wikipedia.org/wiki/Network_address_translation#DNAT) +: पैकेट पर गंतव्य आईपी को प्रतिस्थापित करना; इस पृष्ठ पर, इसका मतलब आमतौर पर {{}} के आईपी पते के साथ प्रतिस्थापित करना है + +[VIP](/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies) +: एक वर्चुअल आईपी पता, जैसे कि कुबेरनेट्स में प्रत्येक {{}} को निर्दिष्ट किया गया है + +[kube-proxy](/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies) +: एक नेटवर्क डेमॉन जो प्रत्येक नोड पर सेवा वीआईपी प्रबंधन को व्यवस्थित करता है + +### Prerequisites + +{{< include "task-tutorial-prereqs.md" >}} + +उदाहरणों में एक छोटे nginx वेबसर्वर का उपयोग किया गया है जो HTTP हेडर के माध्यम से प्राप्त अनुरोधों के स्रोत IP को प्रतिध्वनित करता है। आप इसे निम्न प्रकार से बना सकते हैं: + +{{< note >}} +निम्नलिखित कमांड में दी गई छवि केवल AMD64 आर्किटेक्चर पर चलती है। +{{< /note >}} + +```shell +kubectl create deployment source-ip-app --image=registry.k8s.io/echoserver:1.4 +``` +आउटपुट है: +``` +deployment.apps/source-ip-app created +``` + + +## {{% heading "objectives" %}} + + +* विभिन्न प्रकार की सेवाओं के माध्यम से एक सरल अनुप्रयोग को उजागर करें +* समझें कि प्रत्येक सेवा प्रकार स्रोत IP NAT को कैसे संभालता है +* स्रोत IP को संरक्षित करने में शामिल ट्रेडऑफ़ को समझें + + + + + + +## `Type=ClusterIP` वाली सेवाओं के लिए स्रोत IP + +यदि आप kube-proxy को [iptables मोड](/docs/reference/networking/virtual-ips/#proxy-mode-iptables) +(डिफ़ॉल्ट) में चला रहे हैं, तो क्लस्टर के भीतर से ClusterIP को भेजे गए पैकेट कभी भी स्रोत NAT'd नहीं होते हैं। आप kube-proxy मोड को उस नोड पर `http://localhost:10249/proxyMode` लाकर क्वेरी कर सकते हैं जहाँ kube-proxy चल रहा है। + +```console +kubectl get nodes +``` + +इसका आउटपुट कुछ इस प्रकार है: + +``` +NAME STATUS ROLES AGE VERSION +kubernetes-node-6jst Ready 2h v1.13.0 +kubernetes-node-cx31 Ready 2h v1.13.0 +kubernetes-node-jj1t Ready 2h v1.13.0 +``` + +किसी एक नोड पर प्रॉक्सी मोड प्राप्त करें (kube-proxy पोर्ट 10249 पर सुनता है): + +```shell +# Run this in a shell on the node you want to query. +curl http://localhost:10249/proxyMode +``` + +इसका आउटपुट कुछ इस प्रकार है: + +``` +iptables +``` + +आप स्रोत IP ऐप पर सेवा बनाकर स्रोत IP संरक्षण का परीक्षण कर सकते हैं: + +```shell +kubectl expose deployment source-ip-app --name=clusterip --port=80 --target-port=8080 +``` + +इसका आउटपुट कुछ इस प्रकार है: + +``` +service/clusterip exposed +``` + +```shell +kubectl get svc clusterip +``` + +इसका आउटपुट कुछ इस प्रकार है: + +``` +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +clusterip ClusterIP 10.0.170.92 80/TCP 51s +``` + +और उसी क्लस्टर में एक पॉड से `ClusterIP` को हिट करना: + +```shell +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. + +``` + +फिर आप उस पॉड के अंदर एक कमांड चला सकते हैं: + +```shell +# Run this inside the terminal from "kubectl run" +ip addr +``` +``` +1: lo: 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: 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` का उपयोग करें + +```shell +# 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`](/docs/concepts/services-networking/service/#type-nodeport) के साथ सेवाओं को भेजे गए पैकेट +डिफ़ॉल्ट रूप से स्रोत NAT'd होते हैं। आप `NodePort` सेवा बनाकर इसका परीक्षण कर सकते हैं: + + +```shell +kubectl expose deployment source-ip-app --name=nodeport --port=80 --target-port=8080 --type=NodePort +``` + +इसका आउटपुट कुछ इस प्रकार है: + +``` +service/nodeport exposed +``` + +```shell +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` के लिए फ़ायरवॉल-नियम खोलने की आवश्यकता हो सकती है। अब आप ऊपर आवंटित नोड पोर्ट के माध्यम से क्लस्टर के बाहर से सेवा तक पहुँचने का प्रयास कर सकते हैं। + +```shell +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 पर भेजा जाता है +* पॉड का जवाब वापस क्लाइंट को भेजा जाता है + +दृश्यात्मक रूप से: + +{{< figure src="/docs/images/tutor-service-nodePort-fig01.svg" alt="source IP nodeport figure 01" class="diagram-large" caption="Figure. Source IP Type=NodePort using SNAT" link="https://mermaid.live/edit#pako:eNqNkV9rwyAUxb-K3LysYEqS_WFYKAzat9GHdW9zDxKvi9RoMIZtlH732ZjSbE970cu5v3s86hFqJxEYfHjRNeT5ZcUtIbXRaMNN2hZ5vrYRqt52cSXV-4iMSuwkZiYtyX739EqWaahMQ-V1qPxDVLNOvkYrO6fj2dupWMR2iiT6foOKdEZoS5Q2hmVSStoH7w7IMqXUVOefWoaG3XVftHbGeZYVRbH6ZXJ47CeL2-qhxvt_ucTe1SUlpuMN6CX12XeGpLdJiaMMFFr0rdAyvvfxjHEIDbbIgcVSohKDCRy4PUV06KQIuJU6OA9MCdMjBTEEt_-2NbDgB7xAGy3i97VJPP0ABRmcqg" >}} + +इससे बचने के लिए, Kubernetes में [क्लाइंट स्रोत IP को संरक्षित](/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip) करने की सुविधा है। +यदि आप `service.spec.externalTrafficPolicy` को `Local` मान पर सेट करते हैं, तो kube-proxy केवल स्थानीय एंडपॉइंट पर प्रॉक्सी अनुरोधों को प्रॉक्सी करता है, और ट्रैफ़िक को अन्य नोड्स पर अग्रेषित नहीं करता है। यह दृष्टिकोण मूल स्रोत IP पते को संरक्षित करता है। यदि कोई स्थानीय एंडपॉइंट नहीं हैं, तो नोड पर भेजे गए पैकेट ड्रॉप हो जाते हैं, इसलिए आप किसी भी पैकेट प्रोसेसिंग नियम में सही स्रोत-आईपी पर भरोसा कर सकते हैं, आप एक पैकेट लागू कर सकते हैं जो एंडपॉइंट तक पहुंचता है। + +`service.spec.externalTrafficPolicy` फ़ील्ड को निम्न प्रकार से सेट करें: + +```shell +kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}' +``` + +इसका आउटपुट कुछ इस प्रकार है: + +``` +service/nodeport patched +``` + +अब, परीक्षण पुनः चलाएँ: + +```shell +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 वाले एंडपॉइंट पर रूट करता है + +दृश्यात्मक रूप से: + + +{{< figure src="/docs/images/tutor-service-nodePort-fig02.svg" alt="source IP nodeport figure 02" class="diagram-large" caption="Figure. Source IP Type=NodePort preserves client source IP address" link="" >}} + +## `Type=LoadBalancer` वाली सेवाओं के लिए स्रोत IP + +[`Type=LoadBalancer`](/docs/concepts/services-networking/service/#loadbalancer) के साथ सेवाओं को भेजे गए पैकेट +डिफ़ॉल्ट रूप से स्रोत NAT'd होते हैं, क्योंकि `Ready` स्थिति में सभी शेड्यूल करने योग्य Kubernetes नोड लोड-बैलेंस्ड ट्रैफ़िक के लिए पात्र होते हैं। इसलिए यदि पैकेट बिना किसी एंडपॉइंट के नोड पर पहुंचते हैं, तो सिस्टम इसे एक एंडपॉइंट वाले नोड पर प्रॉक्सी करता है, पैकेट पर स्रोत IP को नोड के IP से बदल देता है (जैसा कि पिछले अनुभाग में वर्णित है)। + +आप लोड बैलेंसर के माध्यम से स्रोत-आईपी-ऐप को उजागर करके इसका परीक्षण कर सकते हैं: + +```shell +kubectl expose deployment source-ip-app --name=loadbalancer --port=80 --target-port=8080 --type=LoadBalancer +``` + +आउटपुट इस प्रकार है:: + +``` +service/loadbalancer exposed +``` + +सेवा के आईपी पते का प्रिंट आउट लें: + +```console +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 +``` + +इसके बाद, इस सेवा के बाहरी-आईपी को अनुरोध भेजें: + +```shell +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](/images/docs/sourceip-externaltrafficpolicy.svg) + +आप एनोटेशन सेट करके इसका परीक्षण कर सकते हैं: + +```shell +kubectl patch svc loadbalancer -p '{"spec":{"externalTrafficPolicy":"Local"}}' +``` + +आपको तुरंत Kubernetes द्वारा आवंटित `service.spec.healthCheckNodePort` फ़ील्ड दिखाई देगी: + +```shell +kubectl get svc loadbalancer -o yaml | grep -i healthCheckNodePort +``` + +आउटपुट इस प्रकार है: + +```yaml +healthCheckNodePort: 32122 +``` + +`service.spec.healthCheckNodePort` फ़ील्ड `/healthz` पर स्वास्थ्य जाँच करने वाले प्रत्येक नोड पर एक पोर्ट की ओर इशारा करता है। +आप इसका परीक्षण कर सकते हैं: + +```shell +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` का उपयोग करें: + +```shell +# Run this locally on a node you choose +curl localhost:32122/healthz +``` + +``` +1 Service Endpoints found +``` + +किसी भिन्न नोड पर आपको भिन्न परिणाम मिल सकता है: + +```shell +# Run this locally on a node you choose +curl localhost:32122/healthz +``` + +``` +No Service Endpoints Found +``` + +{{}} पर चलने वाला एक कंट्रोलर क्लाउड लोड बैलेंसर को आवंटित करने के लिए जिम्मेदार होता है। वही कंट्रोलर प्रत्येक नोड पर इस पोर्ट/पथ की ओर इशारा करते हुए HTTP स्वास्थ्य जांच भी आवंटित करता है। स्वास्थ्य जांच में विफल होने के लिए एंडपॉइंट के बिना 2 नोड्स के लिए लगभग 10 सेकंड प्रतीक्षा करें, फिर लोड बैलेंसर के IPv4 पते को क्वेरी करने के लिए `curl` का उपयोग करें: + +```shell +curl 203.0.113.140 +``` + +आउटपुट इस प्रकार है: + +``` +CLIENT VALUES: +client_address=198.51.100.79 +... +``` + +## क्रॉस-प्लेटफ़ॉर्म समर्थन + +केवल कुछ क्लाउड प्रदाता ही `Type=LoadBalancer` वाली सेवाओं के माध्यम से स्रोत IP संरक्षण के लिए समर्थन प्रदान करते हैं। +आप जिस क्लाउड प्रदाता पर काम कर रहे हैं, वह कुछ अलग-अलग तरीकों से लोडबैलेंसर के लिए अनुरोध को पूरा कर सकता है: + +1. एक प्रॉक्सी के साथ जो क्लाइंट कनेक्शन को समाप्त करता है और आपके नोड्स/एंडपॉइंट्स के लिए एक नया कनेक्शन खोलता है। ऐसे मामलों में स्रोत IP हमेशा क्लाउड LB का होगा, क्लाइंट का नहीं। + +2. एक पैकेट फ़ॉरवर्डर के साथ, जैसे कि क्लाइंट से लोडबैलेंसर VIP को भेजे गए अनुरोध क्लाइंट के स्रोत IP वाले नोड पर समाप्त होते हैं, न कि किसी मध्यवर्ती प्रॉक्सी पर। + +पहली श्रेणी के लोड बैलेंसर को लोडबैलेंसर और बैकएंड के बीच HTTP [फॉरवर्डेड](https://tools.ietf.org/html/rfc7239#section-5.2) या [X-FORWARDED-FOR](https://en.wikipedia.org/wiki/X-Forwarded-For) हेडर या +[प्रॉक्सी प्रोटोकॉल](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) जैसे वास्तविक क्लाइंट IP को संप्रेषित करने के लिए सहमत प्रोटोकॉल का उपयोग करना चाहिए। दूसरी श्रेणी के लोड बैलेंसर सेवा पर `service.spec.healthCheckNodePort` फ़ील्ड में संग्रहीत पोर्ट पर इंगित HTTP स्वास्थ्य जांच बनाकर ऊपर वर्णित सुविधा का लाभ उठा सकते हैं। + + +## {{% heading "cleanup" %}} + + +सेवाएँ समाप्त करें: + +```shell +kubectl delete svc -l app=source-ip-app +``` + +डिप्लॉयमेंट, रेप्लिका सेट और पॉड को समाप्त करें: + +```shell +kubectl delete deployment source-ip-app +``` + + + +## {{% heading "whatsnext" %}} + +* [सेवाओं के माध्यम से एप्लिकेशन कनेक्ट करने](/docs/tutorials/services/connect-applications-service/) के बारे में अधिक जानें +* [बाहरी लोड बैलेंसर बनाने का तरीका](/docs/tasks/access-application-cluster/create-external-load-balancer/) पढ़ें diff --git a/content/hi/examples/README.md b/content/hi/examples/README.md new file mode 100644 index 0000000000000..27fc3da7f55d3 --- /dev/null +++ b/content/hi/examples/README.md @@ -0,0 +1,11 @@ +स्थानीयकरण हेतु परीक्षण चलाने के लिए, निम्नलिखित आदेश का उपयोग करें: + +``` +go test k8s.io/website/content//examples +``` + +जहाँ `` किसी भाषा का दो अक्षर वाला प्रतिनिधित्व है। उदाहरण के लिए: + +``` +go test k8s.io/website/content/en/examples +``` diff --git a/content/hi/examples/access/certificate-signing-request/clusterrole-approve.yaml b/content/hi/examples/access/certificate-signing-request/clusterrole-approve.yaml new file mode 100644 index 0000000000000..e5bcfdc44e2d8 --- /dev/null +++ b/content/hi/examples/access/certificate-signing-request/clusterrole-approve.yaml @@ -0,0 +1,28 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: csr-approver +rules: +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - get + - list + - watch +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests/approval + verbs: + - update +- apiGroups: + - certificates.k8s.io + resources: + - signers + resourceNames: + - example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain + verbs: + - approve + diff --git a/content/hi/examples/access/certificate-signing-request/clusterrole-create.yaml b/content/hi/examples/access/certificate-signing-request/clusterrole-create.yaml new file mode 100644 index 0000000000000..def1b879d8e88 --- /dev/null +++ b/content/hi/examples/access/certificate-signing-request/clusterrole-create.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: csr-creator +rules: +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - create + - get + - list + - watch diff --git a/content/hi/examples/access/certificate-signing-request/clusterrole-sign.yaml b/content/hi/examples/access/certificate-signing-request/clusterrole-sign.yaml new file mode 100644 index 0000000000000..6d1a2f7882cd1 --- /dev/null +++ b/content/hi/examples/access/certificate-signing-request/clusterrole-sign.yaml @@ -0,0 +1,27 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: csr-signer +rules: +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - get + - list + - watch +- apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests/status + verbs: + - update +- apiGroups: + - certificates.k8s.io + resources: + - signers + resourceNames: + - example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain + verbs: + - sign diff --git a/content/hi/examples/access/deployment-replicas-policy.yaml b/content/hi/examples/access/deployment-replicas-policy.yaml new file mode 100644 index 0000000000000..d7d11e9a20ced --- /dev/null +++ b/content/hi/examples/access/deployment-replicas-policy.yaml @@ -0,0 +1,19 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "deploy-replica-policy.example.com" +spec: + paramKind: + apiVersion: rules.example.com/v1 + kind: ReplicaLimit + matchConstraints: + resourceRules: + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments"] + validations: + - expression: "object.spec.replicas <= params.maxReplicas" + messageExpression: "'object.spec.replicas must be no greater than ' + string(params.maxReplicas)" + reason: Invalid + diff --git a/content/hi/examples/access/endpoints-aggregated.yaml b/content/hi/examples/access/endpoints-aggregated.yaml new file mode 100644 index 0000000000000..d238820056afb --- /dev/null +++ b/content/hi/examples/access/endpoints-aggregated.yaml @@ -0,0 +1,20 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + kubernetes.io/description: |- + Add endpoints write permissions to the edit and admin roles. This was + removed by default in 1.22 because of CVE-2021-25740. See + https://issue.k8s.io/103675. This can allow writers to direct LoadBalancer + or Ingress implementations to expose backend IPs that would not otherwise + be accessible, and can circumvent network policies or security controls + intended to prevent/isolate access to those backends. + EndpointSlices were never included in the edit or admin roles, so there + is nothing to restore for the EndpointSlice API. + labels: + rbac.authorization.k8s.io/aggregate-to-edit: "true" + name: custom:aggregate-to-edit:endpoints # you can change this if you wish +rules: + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create", "delete", "deletecollection", "patch", "update"] diff --git a/content/hi/examples/access/image-matches-namespace-environment.policy.yaml b/content/hi/examples/access/image-matches-namespace-environment.policy.yaml new file mode 100644 index 0000000000000..cf7508d253091 --- /dev/null +++ b/content/hi/examples/access/image-matches-namespace-environment.policy.yaml @@ -0,0 +1,28 @@ +# This policy enforces that all containers of a deployment has the image repo match the environment label of its namespace. +# Except for "exempt" deployments, or any containers that do not belong to the "example.com" organization (e.g. common sidecars). +# For example, if the namespace has a label of {"environment": "staging"}, all container images must be either staging.example.com/* +# or do not contain "example.com" at all, unless the deployment has {"exempt": "true"} label. +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "image-matches-namespace-environment.policy.example.com" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments"] + variables: + - name: environment + expression: "'environment' in namespaceObject.metadata.labels ? namespaceObject.metadata.labels['environment'] : 'prod'" + - name: exempt + expression: "'exempt' in object.metadata.labels && object.metadata.labels['exempt'] == 'true'" + - name: containers + expression: "object.spec.template.spec.containers" + - name: containersToCheck + expression: "variables.containers.filter(c, c.image.contains('example.com/'))" + validations: + - expression: "variables.exempt || variables.containersToCheck.all(c, c.image.startsWith(variables.environment + '.'))" + messageExpression: "'only ' + variables.environment + ' images are allowed in namespace ' + namespaceObject.metadata.name" \ No newline at end of file diff --git a/content/hi/examples/access/validating-admission-policy-audit-annotation.yaml b/content/hi/examples/access/validating-admission-policy-audit-annotation.yaml new file mode 100644 index 0000000000000..1c422a825447f --- /dev/null +++ b/content/hi/examples/access/validating-admission-policy-audit-annotation.yaml @@ -0,0 +1,18 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "demo-policy.example.com" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments"] + validations: + - expression: "object.spec.replicas > 50" + messageExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)" + auditAnnotations: + - key: "high-replica-count" + valueExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)" diff --git a/content/hi/examples/access/validating-admission-policy-match-conditions.yaml b/content/hi/examples/access/validating-admission-policy-match-conditions.yaml new file mode 100644 index 0000000000000..eafebd2c2c274 --- /dev/null +++ b/content/hi/examples/access/validating-admission-policy-match-conditions.yaml @@ -0,0 +1,22 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "demo-policy.example.com" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["*"] + apiVersions: ["*"] + operations: ["CREATE", "UPDATE"] + resources: ["*"] + matchConditions: + - name: 'exclude-leases' # Each match condition must have a unique name + expression: '!(request.resource.group == "coordination.k8s.io" && request.resource.resource == "leases")' # Match non-lease resources. + - name: 'exclude-kubelet-requests' + expression: '!("system:nodes" in request.userInfo.groups)' # Match requests made by non-node users. + - name: 'rbac' # Skip RBAC requests. + expression: 'request.resource.group != "rbac.authorization.k8s.io"' + validations: + - expression: "!object.metadata.name.contains('demo') || object.metadata.namespace == 'demo'" + diff --git a/content/hi/examples/admin/cloud/ccm-example.yaml b/content/hi/examples/admin/cloud/ccm-example.yaml new file mode 100644 index 0000000000000..91b7ef2b8944f --- /dev/null +++ b/content/hi/examples/admin/cloud/ccm-example.yaml @@ -0,0 +1,73 @@ +# This is an example of how to set up cloud-controller-manager as a Daemonset in your cluster. +# It assumes that your masters can run pods and has the role node-role.kubernetes.io/master +# Note that this Daemonset will not work straight out of the box for your cloud, this is +# meant to be a guideline. + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cloud-controller-manager + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:cloud-controller-manager +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: cloud-controller-manager + namespace: kube-system +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + k8s-app: cloud-controller-manager + name: cloud-controller-manager + namespace: kube-system +spec: + selector: + matchLabels: + k8s-app: cloud-controller-manager + template: + metadata: + labels: + k8s-app: cloud-controller-manager + spec: + serviceAccountName: cloud-controller-manager + containers: + - name: cloud-controller-manager + # for in-tree providers we use registry.k8s.io/cloud-controller-manager + # this can be replaced with any other image for out-of-tree providers + image: registry.k8s.io/cloud-controller-manager:v1.8.0 + command: + - /usr/local/bin/cloud-controller-manager + - --cloud-provider=[YOUR_CLOUD_PROVIDER] # Add your own cloud provider here! + - --leader-elect=true + - --use-service-account-credentials + # these flags will vary for every cloud provider + - --allocate-node-cidrs=true + - --configure-cloud-routes=true + - --cluster-cidr=172.17.0.0/16 + tolerations: + # this is required so CCM can bootstrap itself + - key: node.cloudprovider.kubernetes.io/uninitialized + value: "true" + effect: NoSchedule + # these tolerations are to have the daemonset runnable on control plane nodes + # remove them if your control plane nodes should not run pods + - key: node-role.kubernetes.io/control-plane + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + # this is to restrict CCM to only run on master nodes + # the node selector may vary depending on your cluster setup + nodeSelector: + node-role.kubernetes.io/master: "" diff --git a/content/hi/examples/admin/dns/busybox.yaml b/content/hi/examples/admin/dns/busybox.yaml new file mode 100644 index 0000000000000..31f009d307291 --- /dev/null +++ b/content/hi/examples/admin/dns/busybox.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: busybox + namespace: default +spec: + containers: + - name: busybox + image: busybox:1.28 + command: + - sleep + - "3600" + imagePullPolicy: IfNotPresent + restartPolicy: Always diff --git a/content/hi/examples/admin/dns/dns-horizontal-autoscaler.yaml b/content/hi/examples/admin/dns/dns-horizontal-autoscaler.yaml new file mode 100644 index 0000000000000..3182fed3c8052 --- /dev/null +++ b/content/hi/examples/admin/dns/dns-horizontal-autoscaler.yaml @@ -0,0 +1,87 @@ +kind: ServiceAccount +apiVersion: v1 +metadata: + name: kube-dns-autoscaler + namespace: kube-system +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: system:kube-dns-autoscaler +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["list", "watch"] + - apiGroups: [""] + resources: ["replicationcontrollers/scale"] + verbs: ["get", "update"] + - apiGroups: ["apps"] + resources: ["deployments/scale", "replicasets/scale"] + verbs: ["get", "update"] +# Remove the configmaps rule once below issue is fixed: +# kubernetes-incubator/cluster-proportional-autoscaler#16 + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "create"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: system:kube-dns-autoscaler +subjects: + - kind: ServiceAccount + name: kube-dns-autoscaler + namespace: kube-system +roleRef: + kind: ClusterRole + name: system:kube-dns-autoscaler + apiGroup: rbac.authorization.k8s.io + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kube-dns-autoscaler + namespace: kube-system + labels: + k8s-app: kube-dns-autoscaler + kubernetes.io/cluster-service: "true" +spec: + selector: + matchLabels: + k8s-app: kube-dns-autoscaler + template: + metadata: + labels: + k8s-app: kube-dns-autoscaler + spec: + priorityClassName: system-cluster-critical + securityContext: + seccompProfile: + type: RuntimeDefault + supplementalGroups: [ 65534 ] + fsGroup: 65534 + nodeSelector: + kubernetes.io/os: linux + containers: + - name: autoscaler + image: registry.k8s.io/cpa/cluster-proportional-autoscaler:1.8.4 + resources: + requests: + cpu: "20m" + memory: "10Mi" + command: + - /cluster-proportional-autoscaler + - --namespace=kube-system + - --configmap=kube-dns-autoscaler + # Should keep target in sync with cluster/addons/dns/kube-dns.yaml.base + - --target= + # When cluster is using large nodes(with more cores), "coresPerReplica" should dominate. + # If using small nodes, "nodesPerReplica" should dominate. + - --default-params={"linear":{"coresPerReplica":256,"nodesPerReplica":16,"preventSinglePointFailure":true,"includeUnschedulableNodes":true}} + - --logtostderr=true + - --v=2 + tolerations: + - key: "CriticalAddonsOnly" + operator: "Exists" + serviceAccountName: kube-dns-autoscaler diff --git a/content/hi/examples/admin/dns/dnsutils.yaml b/content/hi/examples/admin/dns/dnsutils.yaml new file mode 100644 index 0000000000000..e1b3ace336f99 --- /dev/null +++ b/content/hi/examples/admin/dns/dnsutils.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dnsutils + namespace: default +spec: + containers: + - name: dnsutils + image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 + command: + - sleep + - "infinity" + imagePullPolicy: IfNotPresent + restartPolicy: Always diff --git a/content/hi/examples/admin/konnectivity/egress-selector-configuration.yaml b/content/hi/examples/admin/konnectivity/egress-selector-configuration.yaml new file mode 100644 index 0000000000000..631e6cc26862e --- /dev/null +++ b/content/hi/examples/admin/konnectivity/egress-selector-configuration.yaml @@ -0,0 +1,21 @@ +apiVersion: apiserver.k8s.io/v1beta1 +kind: EgressSelectorConfiguration +egressSelections: +# Since we want to control the egress traffic to the cluster, we use the +# "cluster" as the name. Other supported values are "etcd", and "controlplane". +- name: cluster + connection: + # This controls the protocol between the API Server and the Konnectivity + # server. Supported values are "GRPC" and "HTTPConnect". There is no + # end user visible difference between the two modes. You need to set the + # Konnectivity server to work in the same mode. + proxyProtocol: GRPC + transport: + # This controls what transport the API Server uses to communicate with the + # Konnectivity server. UDS is recommended if the Konnectivity server + # locates on the same machine as the API Server. You need to configure the + # Konnectivity server to listen on the same UDS socket. + # The other supported transport is "tcp". You will need to set up TLS + # config to secure the TCP transport. + uds: + udsName: /etc/kubernetes/konnectivity-server/konnectivity-server.socket diff --git a/content/hi/examples/admin/konnectivity/konnectivity-agent.yaml b/content/hi/examples/admin/konnectivity/konnectivity-agent.yaml new file mode 100644 index 0000000000000..cbcbf89114a94 --- /dev/null +++ b/content/hi/examples/admin/konnectivity/konnectivity-agent.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +# Alternatively, you can deploy the agents as Deployments. It is not necessary +# to have an agent on each node. +kind: DaemonSet +metadata: + labels: + addonmanager.kubernetes.io/mode: Reconcile + k8s-app: konnectivity-agent + namespace: kube-system + name: konnectivity-agent +spec: + selector: + matchLabels: + k8s-app: konnectivity-agent + template: + metadata: + labels: + k8s-app: konnectivity-agent + spec: + priorityClassName: system-cluster-critical + tolerations: + - key: "CriticalAddonsOnly" + operator: "Exists" + containers: + - image: us.gcr.io/k8s-artifacts-prod/kas-network-proxy/proxy-agent:v0.0.37 + name: konnectivity-agent + command: ["/proxy-agent"] + args: [ + "--logtostderr=true", + "--ca-cert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", + # Since the konnectivity server runs with hostNetwork=true, + # this is the IP address of the master machine. + "--proxy-server-host=35.225.206.7", + "--proxy-server-port=8132", + "--admin-server-port=8133", + "--health-server-port=8134", + "--service-account-token-path=/var/run/secrets/tokens/konnectivity-agent-token" + ] + volumeMounts: + - mountPath: /var/run/secrets/tokens + name: konnectivity-agent-token + livenessProbe: + httpGet: + port: 8134 + path: /healthz + initialDelaySeconds: 15 + timeoutSeconds: 15 + serviceAccountName: konnectivity-agent + volumes: + - name: konnectivity-agent-token + projected: + sources: + - serviceAccountToken: + path: konnectivity-agent-token + audience: system:konnectivity-server diff --git a/content/hi/examples/admin/konnectivity/konnectivity-rbac.yaml b/content/hi/examples/admin/konnectivity/konnectivity-rbac.yaml new file mode 100644 index 0000000000000..7687f49b77e82 --- /dev/null +++ b/content/hi/examples/admin/konnectivity/konnectivity-rbac.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:konnectivity-server + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - apiGroup: rbac.authorization.k8s.io + kind: User + name: system:konnectivity-server +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: konnectivity-agent + namespace: kube-system + labels: + kubernetes.io/cluster-service: "true" + addonmanager.kubernetes.io/mode: Reconcile diff --git a/content/hi/examples/admin/konnectivity/konnectivity-server.yaml b/content/hi/examples/admin/konnectivity/konnectivity-server.yaml new file mode 100644 index 0000000000000..4dfbf5db9d11a --- /dev/null +++ b/content/hi/examples/admin/konnectivity/konnectivity-server.yaml @@ -0,0 +1,73 @@ +apiVersion: v1 +kind: Pod +metadata: + name: konnectivity-server + namespace: kube-system +spec: + priorityClassName: system-cluster-critical + hostNetwork: true + containers: + - name: konnectivity-server-container + image: registry.k8s.io/kas-network-proxy/proxy-server:v0.0.37 + command: ["/proxy-server"] + args: [ + "--logtostderr=true", + # This needs to be consistent with the value set in egressSelectorConfiguration. + "--uds-name=/etc/kubernetes/konnectivity-server/konnectivity-server.socket", + "--delete-existing-uds-file", + # The following two lines assume the Konnectivity server is + # deployed on the same machine as the apiserver, and the certs and + # key of the API Server are at the specified location. + "--cluster-cert=/etc/kubernetes/pki/apiserver.crt", + "--cluster-key=/etc/kubernetes/pki/apiserver.key", + # This needs to be consistent with the value set in egressSelectorConfiguration. + "--mode=grpc", + "--server-port=0", + "--agent-port=8132", + "--admin-port=8133", + "--health-port=8134", + "--agent-namespace=kube-system", + "--agent-service-account=konnectivity-agent", + "--kubeconfig=/etc/kubernetes/konnectivity-server.conf", + "--authentication-audience=system:konnectivity-server" + ] + livenessProbe: + httpGet: + scheme: HTTP + host: 127.0.0.1 + port: 8134 + path: /healthz + initialDelaySeconds: 30 + timeoutSeconds: 60 + ports: + - name: agentport + containerPort: 8132 + hostPort: 8132 + - name: adminport + containerPort: 8133 + hostPort: 8133 + - name: healthport + containerPort: 8134 + hostPort: 8134 + volumeMounts: + - name: k8s-certs + mountPath: /etc/kubernetes/pki + readOnly: true + - name: kubeconfig + mountPath: /etc/kubernetes/konnectivity-server.conf + readOnly: true + - name: konnectivity-uds + mountPath: /etc/kubernetes/konnectivity-server + readOnly: false + volumes: + - name: k8s-certs + hostPath: + path: /etc/kubernetes/pki + - name: kubeconfig + hostPath: + path: /etc/kubernetes/konnectivity-server.conf + type: FileOrCreate + - name: konnectivity-uds + hostPath: + path: /etc/kubernetes/konnectivity-server + type: DirectoryOrCreate diff --git a/content/hi/examples/admin/logging/fluentd-sidecar-config.yaml b/content/hi/examples/admin/logging/fluentd-sidecar-config.yaml new file mode 100644 index 0000000000000..eea1849b033fa --- /dev/null +++ b/content/hi/examples/admin/logging/fluentd-sidecar-config.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: fluentd-config +data: + fluentd.conf: | + + type tail + format none + path /var/log/1.log + pos_file /var/log/1.log.pos + tag count.format1 + + + + type tail + format none + path /var/log/2.log + pos_file /var/log/2.log.pos + tag count.format2 + + + + type google_cloud + diff --git a/content/hi/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml b/content/hi/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml new file mode 100644 index 0000000000000..a621a9fb2acce --- /dev/null +++ b/content/hi/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox:1.28 + args: + - /bin/sh + - -c + - > + i=0; + while true; + do + echo "$i: $(date)" >> /var/log/1.log; + echo "$(date) INFO $i" >> /var/log/2.log; + i=$((i+1)); + sleep 1; + done + volumeMounts: + - name: varlog + mountPath: /var/log + - name: count-agent + image: registry.k8s.io/fluentd-gcp:1.30 + env: + - name: FLUENTD_ARGS + value: -c /etc/fluentd-config/fluentd.conf + volumeMounts: + - name: varlog + mountPath: /var/log + - name: config-volume + mountPath: /etc/fluentd-config + volumes: + - name: varlog + emptyDir: {} + - name: config-volume + configMap: + name: fluentd-config diff --git a/content/hi/examples/admin/logging/two-files-counter-pod-streaming-sidecar.yaml b/content/hi/examples/admin/logging/two-files-counter-pod-streaming-sidecar.yaml new file mode 100644 index 0000000000000..ac19efe4a2350 --- /dev/null +++ b/content/hi/examples/admin/logging/two-files-counter-pod-streaming-sidecar.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox:1.28 + args: + - /bin/sh + - -c + - > + i=0; + while true; + do + echo "$i: $(date)" >> /var/log/1.log; + echo "$(date) INFO $i" >> /var/log/2.log; + i=$((i+1)); + sleep 1; + done + volumeMounts: + - name: varlog + mountPath: /var/log + - name: count-log-1 + image: busybox:1.28 + args: [/bin/sh, -c, 'tail -n+1 -F /var/log/1.log'] + volumeMounts: + - name: varlog + mountPath: /var/log + - name: count-log-2 + image: busybox:1.28 + args: [/bin/sh, -c, 'tail -n+1 -F /var/log/2.log'] + volumeMounts: + - name: varlog + mountPath: /var/log + volumes: + - name: varlog + emptyDir: {} diff --git a/content/hi/examples/admin/logging/two-files-counter-pod.yaml b/content/hi/examples/admin/logging/two-files-counter-pod.yaml new file mode 100644 index 0000000000000..31bbed3cf8683 --- /dev/null +++ b/content/hi/examples/admin/logging/two-files-counter-pod.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox:1.28 + args: + - /bin/sh + - -c + - > + i=0; + while true; + do + echo "$i: $(date)" >> /var/log/1.log; + echo "$(date) INFO $i" >> /var/log/2.log; + i=$((i+1)); + sleep 1; + done + volumeMounts: + - name: varlog + mountPath: /var/log + volumes: + - name: varlog + emptyDir: {} diff --git a/content/hi/examples/admin/namespace-dev.json b/content/hi/examples/admin/namespace-dev.json new file mode 100644 index 0000000000000..cb3ed7cdc1efa --- /dev/null +++ b/content/hi/examples/admin/namespace-dev.json @@ -0,0 +1,10 @@ +{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "name": "development", + "labels": { + "name": "development" + } + } +} diff --git a/content/hi/examples/admin/namespace-dev.yaml b/content/hi/examples/admin/namespace-dev.yaml new file mode 100644 index 0000000000000..5e753b693f03b --- /dev/null +++ b/content/hi/examples/admin/namespace-dev.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: development + labels: + name: development diff --git a/content/hi/examples/admin/namespace-prod.json b/content/hi/examples/admin/namespace-prod.json new file mode 100644 index 0000000000000..878ba7866ca59 --- /dev/null +++ b/content/hi/examples/admin/namespace-prod.json @@ -0,0 +1,10 @@ +{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "name": "production", + "labels": { + "name": "production" + } + } +} diff --git a/content/hi/examples/admin/namespace-prod.yaml b/content/hi/examples/admin/namespace-prod.yaml new file mode 100644 index 0000000000000..761d6325cb404 --- /dev/null +++ b/content/hi/examples/admin/namespace-prod.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: production + labels: + name: production diff --git a/content/hi/examples/admin/resource/cpu-constraints-pod-2.yaml b/content/hi/examples/admin/resource/cpu-constraints-pod-2.yaml new file mode 100644 index 0000000000000..b5c7348f26ee0 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-constraints-pod-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo-2 +spec: + containers: + - name: constraints-cpu-demo-2-ctr + image: nginx + resources: + limits: + cpu: "1.5" + requests: + cpu: "500m" diff --git a/content/hi/examples/admin/resource/cpu-constraints-pod-3.yaml b/content/hi/examples/admin/resource/cpu-constraints-pod-3.yaml new file mode 100644 index 0000000000000..0a2083acd8ec6 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-constraints-pod-3.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo-3 +spec: + containers: + - name: constraints-cpu-demo-3-ctr + image: nginx + resources: + limits: + cpu: "800m" + requests: + cpu: "100m" diff --git a/content/hi/examples/admin/resource/cpu-constraints-pod-4.yaml b/content/hi/examples/admin/resource/cpu-constraints-pod-4.yaml new file mode 100644 index 0000000000000..3c102158db509 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-constraints-pod-4.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo-4 +spec: + containers: + - name: constraints-cpu-demo-4-ctr + image: vish/stress diff --git a/content/hi/examples/admin/resource/cpu-constraints-pod.yaml b/content/hi/examples/admin/resource/cpu-constraints-pod.yaml new file mode 100644 index 0000000000000..7db23f26c8842 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-constraints-pod.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo +spec: + containers: + - name: constraints-cpu-demo-ctr + image: nginx + resources: + limits: + cpu: "800m" + requests: + cpu: "500m" diff --git a/content/hi/examples/admin/resource/cpu-constraints.yaml b/content/hi/examples/admin/resource/cpu-constraints.yaml new file mode 100644 index 0000000000000..6fc4239027c86 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-constraints.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: cpu-min-max-demo-lr +spec: + limits: + - max: + cpu: "800m" + min: + cpu: "200m" + type: Container diff --git a/content/hi/examples/admin/resource/cpu-defaults-pod-2.yaml b/content/hi/examples/admin/resource/cpu-defaults-pod-2.yaml new file mode 100644 index 0000000000000..9ca216dee1557 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-defaults-pod-2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-cpu-demo-2 +spec: + containers: + - name: default-cpu-demo-2-ctr + image: nginx + resources: + limits: + cpu: "1" diff --git a/content/hi/examples/admin/resource/cpu-defaults-pod-3.yaml b/content/hi/examples/admin/resource/cpu-defaults-pod-3.yaml new file mode 100644 index 0000000000000..214cdee34bfff --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-defaults-pod-3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-cpu-demo-3 +spec: + containers: + - name: default-cpu-demo-3-ctr + image: nginx + resources: + requests: + cpu: "0.75" diff --git a/content/hi/examples/admin/resource/cpu-defaults-pod.yaml b/content/hi/examples/admin/resource/cpu-defaults-pod.yaml new file mode 100644 index 0000000000000..56b06d9a690e5 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-defaults-pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-cpu-demo +spec: + containers: + - name: default-cpu-demo-ctr + image: nginx diff --git a/content/hi/examples/admin/resource/cpu-defaults.yaml b/content/hi/examples/admin/resource/cpu-defaults.yaml new file mode 100644 index 0000000000000..b53d297181683 --- /dev/null +++ b/content/hi/examples/admin/resource/cpu-defaults.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: cpu-limit-range +spec: + limits: + - default: + cpu: 1 + defaultRequest: + cpu: 0.5 + type: Container diff --git a/content/hi/examples/admin/resource/limit-mem-cpu-container.yaml b/content/hi/examples/admin/resource/limit-mem-cpu-container.yaml new file mode 100644 index 0000000000000..3c2b30f29ccef --- /dev/null +++ b/content/hi/examples/admin/resource/limit-mem-cpu-container.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: limit-mem-cpu-per-container +spec: + limits: + - max: + cpu: "800m" + memory: "1Gi" + min: + cpu: "100m" + memory: "99Mi" + default: + cpu: "700m" + memory: "900Mi" + defaultRequest: + cpu: "110m" + memory: "111Mi" + type: Container diff --git a/content/hi/examples/admin/resource/limit-mem-cpu-pod.yaml b/content/hi/examples/admin/resource/limit-mem-cpu-pod.yaml new file mode 100644 index 0000000000000..0ce0f69ac8130 --- /dev/null +++ b/content/hi/examples/admin/resource/limit-mem-cpu-pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: limit-mem-cpu-per-pod +spec: + limits: + - max: + cpu: "2" + memory: "2Gi" + type: Pod diff --git a/content/hi/examples/admin/resource/limit-memory-ratio-pod.yaml b/content/hi/examples/admin/resource/limit-memory-ratio-pod.yaml new file mode 100644 index 0000000000000..859fc20ecec38 --- /dev/null +++ b/content/hi/examples/admin/resource/limit-memory-ratio-pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: limit-memory-ratio-pod +spec: + limits: + - maxLimitRequestRatio: + memory: 2 + type: Pod diff --git a/content/hi/examples/admin/resource/limit-range-pod-1.yaml b/content/hi/examples/admin/resource/limit-range-pod-1.yaml new file mode 100644 index 0000000000000..b9bd20d06a2c7 --- /dev/null +++ b/content/hi/examples/admin/resource/limit-range-pod-1.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: Pod +metadata: + name: busybox1 +spec: + containers: + - name: busybox-cnt01 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt01; sleep 10;done"] + resources: + requests: + memory: "100Mi" + cpu: "100m" + limits: + memory: "200Mi" + cpu: "500m" + - name: busybox-cnt02 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"] + resources: + requests: + memory: "100Mi" + cpu: "100m" + - name: busybox-cnt03 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt03; sleep 10;done"] + resources: + limits: + memory: "200Mi" + cpu: "500m" + - name: busybox-cnt04 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt04; sleep 10;done"] diff --git a/content/hi/examples/admin/resource/limit-range-pod-2.yaml b/content/hi/examples/admin/resource/limit-range-pod-2.yaml new file mode 100644 index 0000000000000..40da19c1aee05 --- /dev/null +++ b/content/hi/examples/admin/resource/limit-range-pod-2.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: Pod +metadata: + name: busybox2 +spec: + containers: + - name: busybox-cnt01 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt01; sleep 10;done"] + resources: + requests: + memory: "100Mi" + cpu: "100m" + limits: + memory: "200Mi" + cpu: "500m" + - name: busybox-cnt02 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"] + resources: + requests: + memory: "100Mi" + cpu: "100m" + - name: busybox-cnt03 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt03; sleep 10;done"] + resources: + limits: + memory: "200Mi" + cpu: "500m" + - name: busybox-cnt04 + image: busybox:1.28 + command: ["/bin/sh"] + args: ["-c", "while true; do echo hello from cnt04; sleep 10;done"] diff --git a/content/hi/examples/admin/resource/limit-range-pod-3.yaml b/content/hi/examples/admin/resource/limit-range-pod-3.yaml new file mode 100644 index 0000000000000..5b6b835e38b62 --- /dev/null +++ b/content/hi/examples/admin/resource/limit-range-pod-3.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: busybox3 +spec: + containers: + - name: busybox-cnt01 + image: busybox:1.28 + command: ["sleep", "3600"] + resources: + limits: + memory: "300Mi" + requests: + memory: "100Mi" diff --git a/content/hi/examples/admin/resource/memory-available-cgroupv2.sh b/content/hi/examples/admin/resource/memory-available-cgroupv2.sh new file mode 100644 index 0000000000000..47b9f6802bdfd --- /dev/null +++ b/content/hi/examples/admin/resource/memory-available-cgroupv2.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# This script reproduces what the kubelet does +# to calculate memory.available relative to kubepods cgroup. + +# current memory usage +memory_capacity_in_kb=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}') +memory_capacity_in_bytes=$((memory_capacity_in_kb * 1024)) +memory_usage_in_bytes=$(cat /sys/fs/cgroup/kubepods.slice/memory.current) +memory_total_inactive_file=$(cat /sys/fs/cgroup/kubepods.slice/memory.stat | grep inactive_file | awk '{print $2}') + +memory_working_set=${memory_usage_in_bytes} +if [ "$memory_working_set" -lt "$memory_total_inactive_file" ]; +then + memory_working_set=0 +else + memory_working_set=$((memory_usage_in_bytes - memory_total_inactive_file)) +fi + +memory_available_in_bytes=$((memory_capacity_in_bytes - memory_working_set)) +memory_available_in_kb=$((memory_available_in_bytes / 1024)) +memory_available_in_mb=$((memory_available_in_kb / 1024)) + +echo "memory.capacity_in_bytes $memory_capacity_in_bytes" +echo "memory.usage_in_bytes $memory_usage_in_bytes" +echo "memory.total_inactive_file $memory_total_inactive_file" +echo "memory.working_set $memory_working_set" +echo "memory.available_in_bytes $memory_available_in_bytes" +echo "memory.available_in_kb $memory_available_in_kb" +echo "memory.available_in_mb $memory_available_in_mb" diff --git a/content/hi/examples/admin/resource/memory-available.sh b/content/hi/examples/admin/resource/memory-available.sh new file mode 100644 index 0000000000000..a699b1d2e2046 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-available.sh @@ -0,0 +1,31 @@ +#!/bin/bash +#!/usr/bin/env bash + +# This script reproduces what the kubelet does +# to calculate memory.available relative to root cgroup. + +# current memory usage +memory_capacity_in_kb=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}') +memory_capacity_in_bytes=$((memory_capacity_in_kb * 1024)) +memory_usage_in_bytes=$(cat /sys/fs/cgroup/memory/memory.usage_in_bytes) +memory_total_inactive_file=$(cat /sys/fs/cgroup/memory/memory.stat | grep total_inactive_file | awk '{print $2}') + +memory_working_set=${memory_usage_in_bytes} +if [ "$memory_working_set" -lt "$memory_total_inactive_file" ]; +then + memory_working_set=0 +else + memory_working_set=$((memory_usage_in_bytes - memory_total_inactive_file)) +fi + +memory_available_in_bytes=$((memory_capacity_in_bytes - memory_working_set)) +memory_available_in_kb=$((memory_available_in_bytes / 1024)) +memory_available_in_mb=$((memory_available_in_kb / 1024)) + +echo "memory.capacity_in_bytes $memory_capacity_in_bytes" +echo "memory.usage_in_bytes $memory_usage_in_bytes" +echo "memory.total_inactive_file $memory_total_inactive_file" +echo "memory.working_set $memory_working_set" +echo "memory.available_in_bytes $memory_available_in_bytes" +echo "memory.available_in_kb $memory_available_in_kb" +echo "memory.available_in_mb $memory_available_in_mb" diff --git a/content/hi/examples/admin/resource/memory-constraints-pod-2.yaml b/content/hi/examples/admin/resource/memory-constraints-pod-2.yaml new file mode 100644 index 0000000000000..0b1ae569c4962 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-constraints-pod-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo-2 +spec: + containers: + - name: constraints-mem-demo-2-ctr + image: nginx + resources: + limits: + memory: "1.5Gi" + requests: + memory: "800Mi" diff --git a/content/hi/examples/admin/resource/memory-constraints-pod-3.yaml b/content/hi/examples/admin/resource/memory-constraints-pod-3.yaml new file mode 100644 index 0000000000000..f97cd4a8ac07f --- /dev/null +++ b/content/hi/examples/admin/resource/memory-constraints-pod-3.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo-3 +spec: + containers: + - name: constraints-mem-demo-3-ctr + image: nginx + resources: + limits: + memory: "800Mi" + requests: + memory: "100Mi" diff --git a/content/hi/examples/admin/resource/memory-constraints-pod-4.yaml b/content/hi/examples/admin/resource/memory-constraints-pod-4.yaml new file mode 100644 index 0000000000000..657530c41e7fc --- /dev/null +++ b/content/hi/examples/admin/resource/memory-constraints-pod-4.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo-4 +spec: + containers: + - name: constraints-mem-demo-4-ctr + image: nginx + diff --git a/content/hi/examples/admin/resource/memory-constraints-pod.yaml b/content/hi/examples/admin/resource/memory-constraints-pod.yaml new file mode 100644 index 0000000000000..06954d10d65ad --- /dev/null +++ b/content/hi/examples/admin/resource/memory-constraints-pod.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo +spec: + containers: + - name: constraints-mem-demo-ctr + image: nginx + resources: + limits: + memory: "800Mi" + requests: + memory: "600Mi" diff --git a/content/hi/examples/admin/resource/memory-constraints.yaml b/content/hi/examples/admin/resource/memory-constraints.yaml new file mode 100644 index 0000000000000..3a2924c032e50 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-constraints.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: mem-min-max-demo-lr +spec: + limits: + - max: + memory: 1Gi + min: + memory: 500Mi + type: Container diff --git a/content/hi/examples/admin/resource/memory-defaults-pod-2.yaml b/content/hi/examples/admin/resource/memory-defaults-pod-2.yaml new file mode 100644 index 0000000000000..aa80610d84492 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-defaults-pod-2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-mem-demo-2 +spec: + containers: + - name: default-mem-demo-2-ctr + image: nginx + resources: + limits: + memory: "1Gi" diff --git a/content/hi/examples/admin/resource/memory-defaults-pod-3.yaml b/content/hi/examples/admin/resource/memory-defaults-pod-3.yaml new file mode 100644 index 0000000000000..09ee8b39a9b42 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-defaults-pod-3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-mem-demo-3 +spec: + containers: + - name: default-mem-demo-3-ctr + image: nginx + resources: + requests: + memory: "128Mi" diff --git a/content/hi/examples/admin/resource/memory-defaults-pod.yaml b/content/hi/examples/admin/resource/memory-defaults-pod.yaml new file mode 100644 index 0000000000000..ce7a50fb555e0 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-defaults-pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-mem-demo +spec: + containers: + - name: default-mem-demo-ctr + image: nginx diff --git a/content/hi/examples/admin/resource/memory-defaults.yaml b/content/hi/examples/admin/resource/memory-defaults.yaml new file mode 100644 index 0000000000000..b98a5ae262561 --- /dev/null +++ b/content/hi/examples/admin/resource/memory-defaults.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: mem-limit-range +spec: + limits: + - default: + memory: 512Mi + defaultRequest: + memory: 256Mi + type: Container diff --git a/content/hi/examples/admin/resource/pvc-limit-greater.yaml b/content/hi/examples/admin/resource/pvc-limit-greater.yaml new file mode 100644 index 0000000000000..2d92bf92b3121 --- /dev/null +++ b/content/hi/examples/admin/resource/pvc-limit-greater.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-limit-greater +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi diff --git a/content/hi/examples/admin/resource/pvc-limit-lower.yaml b/content/hi/examples/admin/resource/pvc-limit-lower.yaml new file mode 100644 index 0000000000000..ef819b6292049 --- /dev/null +++ b/content/hi/examples/admin/resource/pvc-limit-lower.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-limit-lower +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 500Mi diff --git a/content/hi/examples/admin/resource/quota-mem-cpu-pod-2.yaml b/content/hi/examples/admin/resource/quota-mem-cpu-pod-2.yaml new file mode 100644 index 0000000000000..380e900fda52f --- /dev/null +++ b/content/hi/examples/admin/resource/quota-mem-cpu-pod-2.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: quota-mem-cpu-demo-2 +spec: + containers: + - name: quota-mem-cpu-demo-2-ctr + image: redis + resources: + limits: + memory: "1Gi" + cpu: "800m" + requests: + memory: "700Mi" + cpu: "400m" diff --git a/content/hi/examples/admin/resource/quota-mem-cpu-pod.yaml b/content/hi/examples/admin/resource/quota-mem-cpu-pod.yaml new file mode 100644 index 0000000000000..b0fd0a9451bf2 --- /dev/null +++ b/content/hi/examples/admin/resource/quota-mem-cpu-pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: quota-mem-cpu-demo +spec: + containers: + - name: quota-mem-cpu-demo-ctr + image: nginx + resources: + limits: + memory: "800Mi" + cpu: "800m" + requests: + memory: "600Mi" + cpu: "400m" diff --git a/content/hi/examples/admin/resource/quota-mem-cpu.yaml b/content/hi/examples/admin/resource/quota-mem-cpu.yaml new file mode 100644 index 0000000000000..5c4bcd81b8b35 --- /dev/null +++ b/content/hi/examples/admin/resource/quota-mem-cpu.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: mem-cpu-demo +spec: + hard: + requests.cpu: "1" + requests.memory: 1Gi + limits.cpu: "2" + limits.memory: 2Gi diff --git a/content/hi/examples/admin/resource/quota-objects-pvc-2.yaml b/content/hi/examples/admin/resource/quota-objects-pvc-2.yaml new file mode 100644 index 0000000000000..2539c2d3093a8 --- /dev/null +++ b/content/hi/examples/admin/resource/quota-objects-pvc-2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-quota-demo-2 +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 4Gi diff --git a/content/hi/examples/admin/resource/quota-objects-pvc.yaml b/content/hi/examples/admin/resource/quota-objects-pvc.yaml new file mode 100644 index 0000000000000..728bb4d708c27 --- /dev/null +++ b/content/hi/examples/admin/resource/quota-objects-pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-quota-demo +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi diff --git a/content/hi/examples/admin/resource/quota-objects.yaml b/content/hi/examples/admin/resource/quota-objects.yaml new file mode 100644 index 0000000000000..e97748decd53a --- /dev/null +++ b/content/hi/examples/admin/resource/quota-objects.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: object-quota-demo +spec: + hard: + persistentvolumeclaims: "1" + services.loadbalancers: "2" + services.nodeports: "0" diff --git a/content/hi/examples/admin/resource/quota-pod-deployment.yaml b/content/hi/examples/admin/resource/quota-pod-deployment.yaml new file mode 100644 index 0000000000000..86e85aa468e13 --- /dev/null +++ b/content/hi/examples/admin/resource/quota-pod-deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pod-quota-demo +spec: + selector: + matchLabels: + purpose: quota-demo + replicas: 3 + template: + metadata: + labels: + purpose: quota-demo + spec: + containers: + - name: pod-quota-demo + image: nginx diff --git a/content/hi/examples/admin/resource/quota-pod.yaml b/content/hi/examples/admin/resource/quota-pod.yaml new file mode 100644 index 0000000000000..0a07f055ca853 --- /dev/null +++ b/content/hi/examples/admin/resource/quota-pod.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: pod-demo +spec: + hard: + pods: "2" diff --git a/content/hi/examples/admin/resource/storagelimits.yaml b/content/hi/examples/admin/resource/storagelimits.yaml new file mode 100644 index 0000000000000..7f597e4dfe9b1 --- /dev/null +++ b/content/hi/examples/admin/resource/storagelimits.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: storagelimits +spec: + limits: + - type: PersistentVolumeClaim + max: + storage: 2Gi + min: + storage: 1Gi diff --git a/content/hi/examples/admin/sched/clusterrole.yaml b/content/hi/examples/admin/sched/clusterrole.yaml new file mode 100644 index 0000000000000..554b8659db5b0 --- /dev/null +++ b/content/hi/examples/admin/sched/clusterrole.yaml @@ -0,0 +1,37 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + labels: + kubernetes.io/bootstrapping: rbac-defaults + name: system:kube-scheduler +rules: + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - coordination.k8s.io + resourceNames: + - kube-scheduler + - my-scheduler + resources: + - leases + verbs: + - get + - update + - apiGroups: + - "" + resourceNames: + - kube-scheduler + - my-scheduler + resources: + - endpoints + verbs: + - delete + - get + - patch + - update diff --git a/content/hi/examples/admin/sched/my-scheduler.yaml b/content/hi/examples/admin/sched/my-scheduler.yaml new file mode 100644 index 0000000000000..fa1c65bf9a462 --- /dev/null +++ b/content/hi/examples/admin/sched/my-scheduler.yaml @@ -0,0 +1,113 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: my-scheduler + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: my-scheduler-as-kube-scheduler +subjects: +- kind: ServiceAccount + name: my-scheduler + namespace: kube-system +roleRef: + kind: ClusterRole + name: system:kube-scheduler + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: my-scheduler-as-volume-scheduler +subjects: +- kind: ServiceAccount + name: my-scheduler + namespace: kube-system +roleRef: + kind: ClusterRole + name: system:volume-scheduler + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: my-scheduler-extension-apiserver-authentication-reader + namespace: kube-system +roleRef: + kind: Role + name: extension-apiserver-authentication-reader + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: my-scheduler + namespace: kube-system +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: my-scheduler-config + namespace: kube-system +data: + my-scheduler-config.yaml: | + apiVersion: kubescheduler.config.k8s.io/v1beta2 + kind: KubeSchedulerConfiguration + profiles: + - schedulerName: my-scheduler + leaderElection: + leaderElect: false +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + component: scheduler + tier: control-plane + name: my-scheduler + namespace: kube-system +spec: + selector: + matchLabels: + component: scheduler + tier: control-plane + replicas: 1 + template: + metadata: + labels: + component: scheduler + tier: control-plane + version: second + spec: + serviceAccountName: my-scheduler + containers: + - command: + - /usr/local/bin/kube-scheduler + - --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml + image: gcr.io/my-gcp-project/my-kube-scheduler:1.0 + livenessProbe: + httpGet: + path: /healthz + port: 10259 + scheme: HTTPS + initialDelaySeconds: 15 + name: kube-second-scheduler + readinessProbe: + httpGet: + path: /healthz + port: 10259 + scheme: HTTPS + resources: + requests: + cpu: '0.1' + securityContext: + privileged: false + volumeMounts: + - name: config-volume + mountPath: /etc/kubernetes/my-scheduler + hostNetwork: false + hostPID: false + volumes: + - name: config-volume + configMap: + name: my-scheduler-config diff --git a/content/hi/examples/admin/sched/pod1.yaml b/content/hi/examples/admin/sched/pod1.yaml new file mode 100644 index 0000000000000..7183dd62c0f12 --- /dev/null +++ b/content/hi/examples/admin/sched/pod1.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: no-annotation + labels: + name: multischeduler-example +spec: + containers: + - name: pod-with-no-annotation-container + image: registry.k8s.io/pause:2.0 \ No newline at end of file diff --git a/content/hi/examples/admin/sched/pod2.yaml b/content/hi/examples/admin/sched/pod2.yaml new file mode 100644 index 0000000000000..b78ab64a4bc4a --- /dev/null +++ b/content/hi/examples/admin/sched/pod2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: annotation-default-scheduler + labels: + name: multischeduler-example +spec: + schedulerName: default-scheduler + containers: + - name: pod-with-default-annotation-container + image: registry.k8s.io/pause:2.0 diff --git a/content/hi/examples/admin/sched/pod3.yaml b/content/hi/examples/admin/sched/pod3.yaml new file mode 100644 index 0000000000000..661414382913f --- /dev/null +++ b/content/hi/examples/admin/sched/pod3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: annotation-second-scheduler + labels: + name: multischeduler-example +spec: + schedulerName: my-scheduler + containers: + - name: pod-with-second-annotation-container + image: registry.k8s.io/pause:2.0 diff --git a/content/hi/examples/admin/snowflake-deployment.yaml b/content/hi/examples/admin/snowflake-deployment.yaml new file mode 100644 index 0000000000000..21b6738ba4e6d --- /dev/null +++ b/content/hi/examples/admin/snowflake-deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: snowflake + name: snowflake +spec: + replicas: 2 + selector: + matchLabels: + app: snowflake + template: + metadata: + labels: + app: snowflake + spec: + containers: + - image: registry.k8s.io/serve_hostname + imagePullPolicy: Always + name: snowflake diff --git a/content/hi/examples/application/cassandra/cassandra-service.yaml b/content/hi/examples/application/cassandra/cassandra-service.yaml new file mode 100644 index 0000000000000..31bee74b58732 --- /dev/null +++ b/content/hi/examples/application/cassandra/cassandra-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: cassandra + name: cassandra +spec: + clusterIP: None + ports: + - port: 9042 + selector: + app: cassandra diff --git a/content/hi/examples/application/cassandra/cassandra-statefulset.yaml b/content/hi/examples/application/cassandra/cassandra-statefulset.yaml new file mode 100644 index 0000000000000..7e8bf30d85add --- /dev/null +++ b/content/hi/examples/application/cassandra/cassandra-statefulset.yaml @@ -0,0 +1,100 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: cassandra + labels: + app: cassandra +spec: + serviceName: cassandra + replicas: 3 + selector: + matchLabels: + app: cassandra + template: + metadata: + labels: + app: cassandra + spec: + terminationGracePeriodSeconds: 500 + containers: + - name: cassandra + image: gcr.io/google-samples/cassandra:v13 + imagePullPolicy: Always + ports: + - containerPort: 7000 + name: intra-node + - containerPort: 7001 + name: tls-intra-node + - containerPort: 7199 + name: jmx + - containerPort: 9042 + name: cql + resources: + limits: + cpu: "500m" + memory: 1Gi + requests: + cpu: "500m" + memory: 1Gi + securityContext: + capabilities: + add: + - IPC_LOCK + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - nodetool drain + env: + - name: MAX_HEAP_SIZE + value: 512M + - name: HEAP_NEWSIZE + value: 100M + - name: CASSANDRA_SEEDS + value: "cassandra-0.cassandra.default.svc.cluster.local" + - name: CASSANDRA_CLUSTER_NAME + value: "K8Demo" + - name: CASSANDRA_DC + value: "DC1-K8Demo" + - name: CASSANDRA_RACK + value: "Rack1-K8Demo" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + readinessProbe: + exec: + command: + - /bin/bash + - -c + - /ready-probe.sh + initialDelaySeconds: 15 + timeoutSeconds: 5 + # These volume mounts are persistent. They are like inline claims, + # but not exactly because the names need to match exactly one of + # the stateful pod volumes. + volumeMounts: + - name: cassandra-data + mountPath: /cassandra_data + # These are converted to volume claims by the controller + # and mounted at the paths mentioned above. + # do not use these in production until ssd GCEPersistentDisk or other ssd pd + volumeClaimTemplates: + - metadata: + name: cassandra-data + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: fast + resources: + requests: + storage: 1Gi +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: fast +provisioner: k8s.io/minikube-hostpath +parameters: + type: pd-ssd diff --git a/content/hi/examples/application/deployment-patch.yaml b/content/hi/examples/application/deployment-patch.yaml new file mode 100644 index 0000000000000..af12f4cb0c4ec --- /dev/null +++ b/content/hi/examples/application/deployment-patch.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: patch-demo +spec: + replicas: 2 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: patch-demo-ctr + image: nginx + tolerations: + - effect: NoSchedule + key: dedicated + value: test-team diff --git a/content/hi/examples/application/deployment-retainkeys.yaml b/content/hi/examples/application/deployment-retainkeys.yaml new file mode 100644 index 0000000000000..af63f46d37294 --- /dev/null +++ b/content/hi/examples/application/deployment-retainkeys.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: retainkeys-demo +spec: + selector: + matchLabels: + app: nginx + strategy: + rollingUpdate: + maxSurge: 30% + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: retainkeys-demo-ctr + image: nginx diff --git a/content/hi/examples/application/deployment-scale.yaml b/content/hi/examples/application/deployment-scale.yaml new file mode 100644 index 0000000000000..838576375ef6f --- /dev/null +++ b/content/hi/examples/application/deployment-scale.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 4 # Update the replicas from 2 to 4 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.16.1 + ports: + - containerPort: 80 diff --git a/content/hi/examples/application/deployment-sidecar.yaml b/content/hi/examples/application/deployment-sidecar.yaml new file mode 100644 index 0000000000000..3f1b841d31ebf --- /dev/null +++ b/content/hi/examples/application/deployment-sidecar.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myapp + labels: + app: myapp +spec: + replicas: 1 + selector: + matchLabels: + app: myapp + template: + metadata: + labels: + app: myapp + spec: + containers: + - name: myapp + image: alpine:latest + command: ['sh', '-c', 'while true; do echo "logging" >> /opt/logs.txt; sleep 1; done'] + volumeMounts: + - name: data + mountPath: /opt + initContainers: + - name: logshipper + image: alpine:latest + restartPolicy: Always + command: ['sh', '-c', 'tail -F /opt/logs.txt'] + volumeMounts: + - name: data + mountPath: /opt + volumes: + - name: data + emptyDir: {} \ No newline at end of file diff --git a/content/hi/examples/application/deployment-update.yaml b/content/hi/examples/application/deployment-update.yaml new file mode 100644 index 0000000000000..1c0b9d1ab8a4f --- /dev/null +++ b/content/hi/examples/application/deployment-update.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 2 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.16.1 # Update the version of nginx from 1.14.2 to 1.16.1 + ports: + - containerPort: 80 diff --git a/content/hi/examples/application/deployment.yaml b/content/hi/examples/application/deployment.yaml new file mode 100644 index 0000000000000..dbed8bc72b9fc --- /dev/null +++ b/content/hi/examples/application/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 2 # tells deployment to run 2 pods matching the template + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/content/hi/examples/application/guestbook/frontend-deployment.yaml b/content/hi/examples/application/guestbook/frontend-deployment.yaml new file mode 100644 index 0000000000000..b4639929ad424 --- /dev/null +++ b/content/hi/examples/application/guestbook/frontend-deployment.yaml @@ -0,0 +1,29 @@ +# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend +spec: + replicas: 3 + selector: + matchLabels: + app: guestbook + tier: frontend + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 + env: + - name: GET_HOSTS_FROM + value: "dns" + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 80 diff --git a/content/hi/examples/application/guestbook/frontend-service.yaml b/content/hi/examples/application/guestbook/frontend-service.yaml new file mode 100644 index 0000000000000..410c6bbaf2950 --- /dev/null +++ b/content/hi/examples/application/guestbook/frontend-service.yaml @@ -0,0 +1,19 @@ +# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: guestbook + tier: frontend +spec: + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + #type: LoadBalancer + ports: + # the port that this service should serve on + - port: 80 + selector: + app: guestbook + tier: frontend \ No newline at end of file diff --git a/content/hi/examples/application/guestbook/redis-follower-deployment.yaml b/content/hi/examples/application/guestbook/redis-follower-deployment.yaml new file mode 100644 index 0000000000000..c32a16e46c879 --- /dev/null +++ b/content/hi/examples/application/guestbook/redis-follower-deployment.yaml @@ -0,0 +1,30 @@ +# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-follower + labels: + app: redis + role: follower + tier: backend +spec: + replicas: 2 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + role: follower + tier: backend + spec: + containers: + - name: follower + image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2 + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 \ No newline at end of file diff --git a/content/hi/examples/application/guestbook/redis-follower-service.yaml b/content/hi/examples/application/guestbook/redis-follower-service.yaml new file mode 100644 index 0000000000000..53283d35c423e --- /dev/null +++ b/content/hi/examples/application/guestbook/redis-follower-service.yaml @@ -0,0 +1,17 @@ +# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook +apiVersion: v1 +kind: Service +metadata: + name: redis-follower + labels: + app: redis + role: follower + tier: backend +spec: + ports: + # the port that this service should serve on + - port: 6379 + selector: + app: redis + role: follower + tier: backend \ No newline at end of file diff --git a/content/hi/examples/application/guestbook/redis-leader-deployment.yaml b/content/hi/examples/application/guestbook/redis-leader-deployment.yaml new file mode 100644 index 0000000000000..9c7547291c376 --- /dev/null +++ b/content/hi/examples/application/guestbook/redis-leader-deployment.yaml @@ -0,0 +1,30 @@ +# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-leader + labels: + app: redis + role: leader + tier: backend +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + role: leader + tier: backend + spec: + containers: + - name: leader + image: "docker.io/redis:6.0.5" + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 \ No newline at end of file diff --git a/content/hi/examples/application/guestbook/redis-leader-service.yaml b/content/hi/examples/application/guestbook/redis-leader-service.yaml new file mode 100644 index 0000000000000..e04cc183d09bf --- /dev/null +++ b/content/hi/examples/application/guestbook/redis-leader-service.yaml @@ -0,0 +1,17 @@ +# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook +apiVersion: v1 +kind: Service +metadata: + name: redis-leader + labels: + app: redis + role: leader + tier: backend +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: redis + role: leader + tier: backend \ No newline at end of file diff --git a/content/hi/examples/application/hpa/php-apache.yaml b/content/hi/examples/application/hpa/php-apache.yaml new file mode 100644 index 0000000000000..1c49aca6a1ff5 --- /dev/null +++ b/content/hi/examples/application/hpa/php-apache.yaml @@ -0,0 +1,18 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: php-apache +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: php-apache + minReplicas: 1 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 diff --git a/content/hi/examples/application/job/cronjob.yaml b/content/hi/examples/application/job/cronjob.yaml new file mode 100644 index 0000000000000..78d0e2d314792 --- /dev/null +++ b/content/hi/examples/application/job/cronjob.yaml @@ -0,0 +1,19 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: hello +spec: + schedule: "* * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: hello + image: busybox:1.28 + imagePullPolicy: IfNotPresent + command: + - /bin/sh + - -c + - date; echo Hello from the Kubernetes cluster + restartPolicy: OnFailure diff --git a/content/hi/examples/application/job/indexed-job-vol.yaml b/content/hi/examples/application/job/indexed-job-vol.yaml new file mode 100644 index 0000000000000..ed40e1cc44606 --- /dev/null +++ b/content/hi/examples/application/job/indexed-job-vol.yaml @@ -0,0 +1,27 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: 'indexed-job' +spec: + completions: 5 + parallelism: 3 + completionMode: Indexed + template: + spec: + restartPolicy: Never + containers: + - name: 'worker' + image: 'docker.io/library/busybox' + command: + - "rev" + - "/input/data.txt" + volumeMounts: + - mountPath: /input + name: input + volumes: + - name: input + downwardAPI: + items: + - path: "data.txt" + fieldRef: + fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index'] \ No newline at end of file diff --git a/content/hi/examples/application/job/indexed-job.yaml b/content/hi/examples/application/job/indexed-job.yaml new file mode 100644 index 0000000000000..5b80d3526491f --- /dev/null +++ b/content/hi/examples/application/job/indexed-job.yaml @@ -0,0 +1,35 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: 'indexed-job' +spec: + completions: 5 + parallelism: 3 + completionMode: Indexed + template: + spec: + restartPolicy: Never + initContainers: + - name: 'input' + image: 'docker.io/library/bash' + command: + - "bash" + - "-c" + - | + items=(foo bar baz qux xyz) + echo ${items[$JOB_COMPLETION_INDEX]} > /input/data.txt + volumeMounts: + - mountPath: /input + name: input + containers: + - name: 'worker' + image: 'docker.io/library/busybox' + command: + - "rev" + - "/input/data.txt" + volumeMounts: + - mountPath: /input + name: input + volumes: + - name: input + emptyDir: {} diff --git a/content/hi/examples/application/job/job-sidecar.yaml b/content/hi/examples/application/job/job-sidecar.yaml new file mode 100644 index 0000000000000..9787ad88515b2 --- /dev/null +++ b/content/hi/examples/application/job/job-sidecar.yaml @@ -0,0 +1,26 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: myjob +spec: + template: + spec: + containers: + - name: myjob + image: alpine:latest + command: ['sh', '-c', 'echo "logging" > /opt/logs.txt'] + volumeMounts: + - name: data + mountPath: /opt + initContainers: + - name: logshipper + image: alpine:latest + restartPolicy: Always + command: ['sh', '-c', 'tail -F /opt/logs.txt'] + volumeMounts: + - name: data + mountPath: /opt + restartPolicy: Never + volumes: + - name: data + emptyDir: {} \ No newline at end of file diff --git a/content/hi/examples/application/job/job-tmpl.yaml b/content/hi/examples/application/job/job-tmpl.yaml new file mode 100644 index 0000000000000..d7dbbafd62bc5 --- /dev/null +++ b/content/hi/examples/application/job/job-tmpl.yaml @@ -0,0 +1,18 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: process-item-$ITEM + labels: + jobgroup: jobexample +spec: + template: + metadata: + name: jobexample + labels: + jobgroup: jobexample + spec: + containers: + - name: c + image: busybox:1.28 + command: ["sh", "-c", "echo Processing item $ITEM && sleep 5"] + restartPolicy: Never diff --git a/content/hi/examples/application/job/rabbitmq/Dockerfile b/content/hi/examples/application/job/rabbitmq/Dockerfile new file mode 100644 index 0000000000000..50faab23f439c --- /dev/null +++ b/content/hi/examples/application/job/rabbitmq/Dockerfile @@ -0,0 +1,10 @@ +# Specify BROKER_URL and QUEUE when running +FROM ubuntu:18.04 + +RUN apt-get update && \ + apt-get install -y curl ca-certificates amqp-tools python \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* +COPY ./worker.py /worker.py + +CMD /usr/bin/amqp-consume --url=$BROKER_URL -q $QUEUE -c 1 /worker.py diff --git a/content/hi/examples/application/job/rabbitmq/job.yaml b/content/hi/examples/application/job/rabbitmq/job.yaml new file mode 100644 index 0000000000000..4e1a61892be6b --- /dev/null +++ b/content/hi/examples/application/job/rabbitmq/job.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: job-wq-1 +spec: + completions: 8 + parallelism: 2 + template: + metadata: + name: job-wq-1 + spec: + containers: + - name: c + image: gcr.io//job-wq-1 + env: + - name: BROKER_URL + value: amqp://guest:guest@rabbitmq-service:5672 + - name: QUEUE + value: job1 + restartPolicy: OnFailure diff --git a/content/hi/examples/application/job/rabbitmq/rabbitmq-service.yaml b/content/hi/examples/application/job/rabbitmq/rabbitmq-service.yaml new file mode 100644 index 0000000000000..2f7fb06dcfed6 --- /dev/null +++ b/content/hi/examples/application/job/rabbitmq/rabbitmq-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + component: rabbitmq + name: rabbitmq-service +spec: + ports: + - port: 5672 + selector: + app.kubernetes.io/name: task-queue + app.kubernetes.io/component: rabbitmq diff --git a/content/hi/examples/application/job/rabbitmq/rabbitmq-statefulset.yaml b/content/hi/examples/application/job/rabbitmq/rabbitmq-statefulset.yaml new file mode 100644 index 0000000000000..502598ddf947e --- /dev/null +++ b/content/hi/examples/application/job/rabbitmq/rabbitmq-statefulset.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + component: rabbitmq + name: rabbitmq +spec: + replicas: 1 + serviceName: rabbitmq-service + selector: + matchLabels: + app.kubernetes.io/name: task-queue + app.kubernetes.io/component: rabbitmq + template: + metadata: + labels: + app.kubernetes.io/name: task-queue + app.kubernetes.io/component: rabbitmq + spec: + containers: + - image: rabbitmq + name: rabbitmq + ports: + - containerPort: 5672 + resources: + requests: + memory: 16M + limits: + cpu: 250m + memory: 512M + volumeMounts: + - mountPath: /var/lib/rabbitmq + name: rabbitmq-data + volumes: + - name: rabbitmq-data + emptyDir: {} diff --git a/content/hi/examples/application/job/rabbitmq/worker.py b/content/hi/examples/application/job/rabbitmq/worker.py new file mode 100644 index 0000000000000..88a7fcf96d91a --- /dev/null +++ b/content/hi/examples/application/job/rabbitmq/worker.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +# Just prints standard out and sleeps for 10 seconds. +import sys +import time +print("Processing " + sys.stdin.readlines()[0]) +time.sleep(10) diff --git a/content/hi/examples/application/job/redis/Dockerfile b/content/hi/examples/application/job/redis/Dockerfile new file mode 100644 index 0000000000000..2de23b3c98340 --- /dev/null +++ b/content/hi/examples/application/job/redis/Dockerfile @@ -0,0 +1,6 @@ +FROM python +RUN pip install redis +COPY ./worker.py /worker.py +COPY ./rediswq.py /rediswq.py + +CMD python worker.py diff --git a/content/hi/examples/application/job/redis/job.yaml b/content/hi/examples/application/job/redis/job.yaml new file mode 100644 index 0000000000000..ee7a06c732986 --- /dev/null +++ b/content/hi/examples/application/job/redis/job.yaml @@ -0,0 +1,14 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: job-wq-2 +spec: + parallelism: 2 + template: + metadata: + name: job-wq-2 + spec: + containers: + - name: c + image: gcr.io/myproject/job-wq-2 + restartPolicy: OnFailure diff --git a/content/hi/examples/application/job/redis/redis-pod.yaml b/content/hi/examples/application/job/redis/redis-pod.yaml new file mode 100644 index 0000000000000..ae0c43a793570 --- /dev/null +++ b/content/hi/examples/application/job/redis/redis-pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis-master + labels: + app: redis +spec: + containers: + - name: master + image: redis + env: + - name: MASTER + value: "true" + ports: + - containerPort: 6379 diff --git a/content/hi/examples/application/job/redis/redis-service.yaml b/content/hi/examples/application/job/redis/redis-service.yaml new file mode 100644 index 0000000000000..85f2ca2271d0b --- /dev/null +++ b/content/hi/examples/application/job/redis/redis-service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: redis diff --git a/content/hi/examples/application/job/redis/rediswq.py b/content/hi/examples/application/job/redis/rediswq.py new file mode 100644 index 0000000000000..2b8e81ceab79d --- /dev/null +++ b/content/hi/examples/application/job/redis/rediswq.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python + +# Based on http://peter-hoffmann.com/2012/python-simple-queue-redis-queue.html +# and the suggestion in the redis documentation for RPOPLPUSH, at +# http://redis.io/commands/rpoplpush, which suggests how to implement a work-queue. + + +import redis +import uuid +import hashlib + +class RedisWQ(object): + """Simple Finite Work Queue with Redis Backend + + This work queue is finite: as long as no more work is added + after workers start, the workers can detect when the queue + is completely empty. + + The items in the work queue are assumed to have unique values. + + This object is not intended to be used by multiple threads + concurrently. + """ + def __init__(self, name, **redis_kwargs): + """The default connection parameters are: host='localhost', port=6379, db=0 + + The work queue is identified by "name". The library may create other + keys with "name" as a prefix. + """ + self._db = redis.StrictRedis(**redis_kwargs) + # The session ID will uniquely identify this "worker". + self._session = str(uuid.uuid4()) + # Work queue is implemented as two queues: main, and processing. + # Work is initially in main, and moved to processing when a client picks it up. + self._main_q_key = name + self._processing_q_key = name + ":processing" + self._lease_key_prefix = name + ":leased_by_session:" + + def sessionID(self): + """Return the ID for this session.""" + return self._session + + def _main_qsize(self): + """Return the size of the main queue.""" + return self._db.llen(self._main_q_key) + + def _processing_qsize(self): + """Return the size of the main queue.""" + return self._db.llen(self._processing_q_key) + + def empty(self): + """Return True if the queue is empty, including work being done, False otherwise. + + False does not necessarily mean that there is work available to work on right now, + """ + return self._main_qsize() == 0 and self._processing_qsize() == 0 + +# TODO: implement this +# def check_expired_leases(self): +# """Return to the work queueReturn True if the queue is empty, False otherwise.""" +# # Processing list should not be _too_ long since it is approximately as long +# # as the number of active and recently active workers. +# processing = self._db.lrange(self._processing_q_key, 0, -1) +# for item in processing: +# # If the lease key is not present for an item (it expired or was +# # never created because the client crashed before creating it) +# # then move the item back to the main queue so others can work on it. +# if not self._lease_exists(item): +# TODO: transactionally move the key from processing queue to +# to main queue, while detecting if a new lease is created +# or if either queue is modified. + + def _itemkey(self, item): + """Returns a string that uniquely identifies an item (bytes).""" + return hashlib.sha224(item).hexdigest() + + def _lease_exists(self, item): + """True if a lease on 'item' exists.""" + return self._db.exists(self._lease_key_prefix + self._itemkey(item)) + + def lease(self, lease_secs=60, block=True, timeout=None): + """Begin working on an item the work queue. + + Lease the item for lease_secs. After that time, other + workers may consider this client to have crashed or stalled + and pick up the item instead. + + If optional args block is true and timeout is None (the default), block + if necessary until an item is available.""" + if block: + item = self._db.brpoplpush(self._main_q_key, self._processing_q_key, timeout=timeout) + else: + item = self._db.rpoplpush(self._main_q_key, self._processing_q_key) + if item: + # Record that we (this session id) are working on a key. Expire that + # note after the lease timeout. + # Note: if we crash at this line of the program, then GC will see no lease + # for this item a later return it to the main queue. + itemkey = self._itemkey(item) + self._db.setex(self._lease_key_prefix + itemkey, lease_secs, self._session) + return item + + def complete(self, value): + """Complete working on the item with 'value'. + + If the lease expired, the item may not have completed, and some + other worker may have picked it up. There is no indication + of what happened. + """ + self._db.lrem(self._processing_q_key, 0, value) + # If we crash here, then the GC code will try to move the value, but it will + # not be here, which is fine. So this does not need to be a transaction. + itemkey = self._itemkey(value) + self._db.delete(self._lease_key_prefix + itemkey) + +# TODO: add functions to clean up all keys associated with "name" when +# processing is complete. + +# TODO: add a function to add an item to the queue. Atomically +# check if the queue is empty and if so fail to add the item +# since other workers might think work is done and be in the process +# of exiting. + +# TODO(etune): move to my own github for hosting, e.g. github.com/erictune/rediswq-py and +# make it so it can be pip installed by anyone (see +# http://stackoverflow.com/questions/8247605/configuring-so-that-pip-install-can-work-from-github) + +# TODO(etune): finish code to GC expired leases, and call periodically +# e.g. each time lease times out. + diff --git a/content/hi/examples/application/job/redis/worker.py b/content/hi/examples/application/job/redis/worker.py new file mode 100644 index 0000000000000..c3523a4e21a48 --- /dev/null +++ b/content/hi/examples/application/job/redis/worker.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +import time +import rediswq + +host="redis" +# Uncomment next two lines if you do not have Kube-DNS working. +# import os +# host = os.getenv("REDIS_SERVICE_HOST") + +q = rediswq.RedisWQ(name="job2", host=host) +print("Worker with sessionID: " + q.sessionID()) +print("Initial queue state: empty=" + str(q.empty())) +while not q.empty(): + item = q.lease(lease_secs=10, block=True, timeout=2) + if item is not None: + itemstr = item.decode("utf-8") + print("Working on " + itemstr) + time.sleep(10) # Put your actual work here instead of sleep. + q.complete(item) + else: + print("Waiting for work") +print("Queue empty, exiting") diff --git a/content/hi/examples/application/mongodb/mongo-deployment.yaml b/content/hi/examples/application/mongodb/mongo-deployment.yaml new file mode 100644 index 0000000000000..04908ce25b1dc --- /dev/null +++ b/content/hi/examples/application/mongodb/mongo-deployment.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongo + labels: + app.kubernetes.io/name: mongo + app.kubernetes.io/component: backend +spec: + selector: + matchLabels: + app.kubernetes.io/name: mongo + app.kubernetes.io/component: backend + replicas: 1 + template: + metadata: + labels: + app.kubernetes.io/name: mongo + app.kubernetes.io/component: backend + spec: + containers: + - name: mongo + image: mongo:4.2 + args: + - --bind_ip + - 0.0.0.0 + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 27017 diff --git a/content/hi/examples/application/mongodb/mongo-service.yaml b/content/hi/examples/application/mongodb/mongo-service.yaml new file mode 100644 index 0000000000000..b9cef607bcf79 --- /dev/null +++ b/content/hi/examples/application/mongodb/mongo-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo + labels: + app.kubernetes.io/name: mongo + app.kubernetes.io/component: backend +spec: + ports: + - port: 27017 + targetPort: 27017 + selector: + app.kubernetes.io/name: mongo + app.kubernetes.io/component: backend diff --git a/content/hi/examples/application/mysql/mysql-configmap.yaml b/content/hi/examples/application/mysql/mysql-configmap.yaml new file mode 100644 index 0000000000000..9adb0344a31a6 --- /dev/null +++ b/content/hi/examples/application/mysql/mysql-configmap.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql + labels: + app: mysql + app.kubernetes.io/name: mysql +data: + primary.cnf: | + # Apply this config only on the primary. + [mysqld] + log-bin + replica.cnf: | + # Apply this config only on replicas. + [mysqld] + super-read-only + diff --git a/content/hi/examples/application/mysql/mysql-deployment.yaml b/content/hi/examples/application/mysql/mysql-deployment.yaml new file mode 100644 index 0000000000000..419fbe03d3ff0 --- /dev/null +++ b/content/hi/examples/application/mysql/mysql-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Service +metadata: + name: mysql +spec: + ports: + - port: 3306 + selector: + app: mysql + clusterIP: None +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql +spec: + selector: + matchLabels: + app: mysql + strategy: + type: Recreate + template: + metadata: + labels: + app: mysql + spec: + containers: + - image: mysql:5.6 + name: mysql + env: + # Use secret in real usage + - name: MYSQL_ROOT_PASSWORD + value: password + ports: + - containerPort: 3306 + name: mysql + volumeMounts: + - name: mysql-persistent-storage + mountPath: /var/lib/mysql + volumes: + - name: mysql-persistent-storage + persistentVolumeClaim: + claimName: mysql-pv-claim diff --git a/content/hi/examples/application/mysql/mysql-pv.yaml b/content/hi/examples/application/mysql/mysql-pv.yaml new file mode 100644 index 0000000000000..c89779a83fd23 --- /dev/null +++ b/content/hi/examples/application/mysql/mysql-pv.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: mysql-pv-volume + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 20Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pv-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi diff --git a/content/hi/examples/application/mysql/mysql-services.yaml b/content/hi/examples/application/mysql/mysql-services.yaml new file mode 100644 index 0000000000000..bc015066780c3 --- /dev/null +++ b/content/hi/examples/application/mysql/mysql-services.yaml @@ -0,0 +1,32 @@ +# Headless service for stable DNS entries of StatefulSet members. +apiVersion: v1 +kind: Service +metadata: + name: mysql + labels: + app: mysql + app.kubernetes.io/name: mysql +spec: + ports: + - name: mysql + port: 3306 + clusterIP: None + selector: + app: mysql +--- +# Client service for connecting to any MySQL instance for reads. +# For writes, you must instead connect to the primary: mysql-0.mysql. +apiVersion: v1 +kind: Service +metadata: + name: mysql-read + labels: + app: mysql + app.kubernetes.io/name: mysql + readonly: "true" +spec: + ports: + - name: mysql + port: 3306 + selector: + app: mysql diff --git a/content/hi/examples/application/mysql/mysql-statefulset.yaml b/content/hi/examples/application/mysql/mysql-statefulset.yaml new file mode 100644 index 0000000000000..67755dbb9e830 --- /dev/null +++ b/content/hi/examples/application/mysql/mysql-statefulset.yaml @@ -0,0 +1,168 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mysql +spec: + selector: + matchLabels: + app: mysql + app.kubernetes.io/name: mysql + serviceName: mysql + replicas: 3 + template: + metadata: + labels: + app: mysql + app.kubernetes.io/name: mysql + spec: + initContainers: + - name: init-mysql + image: mysql:5.7 + command: + - bash + - "-c" + - | + set -ex + # Generate mysql server-id from pod ordinal index. + [[ $HOSTNAME =~ -([0-9]+)$ ]] || exit 1 + ordinal=${BASH_REMATCH[1]} + echo [mysqld] > /mnt/conf.d/server-id.cnf + # Add an offset to avoid reserved server-id=0 value. + echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf + # Copy appropriate conf.d files from config-map to emptyDir. + if [[ $ordinal -eq 0 ]]; then + cp /mnt/config-map/primary.cnf /mnt/conf.d/ + else + cp /mnt/config-map/replica.cnf /mnt/conf.d/ + fi + volumeMounts: + - name: conf + mountPath: /mnt/conf.d + - name: config-map + mountPath: /mnt/config-map + - name: clone-mysql + image: gcr.io/google-samples/xtrabackup:1.0 + command: + - bash + - "-c" + - | + set -ex + # Skip the clone if data already exists. + [[ -d /var/lib/mysql/mysql ]] && exit 0 + # Skip the clone on primary (ordinal index 0). + [[ `hostname` =~ -([0-9]+)$ ]] || exit 1 + ordinal=${BASH_REMATCH[1]} + [[ $ordinal -eq 0 ]] && exit 0 + # Clone data from previous peer. + ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql + # Prepare the backup. + xtrabackup --prepare --target-dir=/var/lib/mysql + volumeMounts: + - name: data + mountPath: /var/lib/mysql + subPath: mysql + - name: conf + mountPath: /etc/mysql/conf.d + containers: + - name: mysql + image: mysql:5.7 + env: + - name: MYSQL_ALLOW_EMPTY_PASSWORD + value: "1" + ports: + - name: mysql + containerPort: 3306 + volumeMounts: + - name: data + mountPath: /var/lib/mysql + subPath: mysql + - name: conf + mountPath: /etc/mysql/conf.d + resources: + requests: + cpu: 500m + memory: 1Gi + livenessProbe: + exec: + command: ["mysqladmin", "ping"] + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + exec: + # Check we can execute queries over TCP (skip-networking is off). + command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"] + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 1 + - name: xtrabackup + image: gcr.io/google-samples/xtrabackup:1.0 + ports: + - name: xtrabackup + containerPort: 3307 + command: + - bash + - "-c" + - | + set -ex + cd /var/lib/mysql + + # Determine binlog position of cloned data, if any. + if [[ -f xtrabackup_slave_info && "x$( change_master_to.sql.in + # Ignore xtrabackup_binlog_info in this case (it's useless). + rm -f xtrabackup_slave_info xtrabackup_binlog_info + elif [[ -f xtrabackup_binlog_info ]]; then + # We're cloning directly from primary. Parse binlog position. + [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1 + rm -f xtrabackup_binlog_info xtrabackup_slave_info + echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\ + MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in + fi + + # Check if we need to complete a clone by starting replication. + if [[ -f change_master_to.sql.in ]]; then + echo "Waiting for mysqld to be ready (accepting connections)" + until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done + + echo "Initializing replication from clone position" + mysql -h 127.0.0.1 \ + -e "$( + # /var/lib/docker/containers/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b/997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b-json.log + # The /var/log directory on the host is mapped to the /var/log directory in the container + # running this instance of Fluentd and we end up collecting the file: + # /var/log/containers/synthetic-logger-0.25lps-pod_default-synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log + # This results in the tag: + # var.log.containers.synthetic-logger-0.25lps-pod_default-synth-lgr-997599971ee6366d4a5920d25b79286ad45ff37a74494f262e3bc98d909d0a7b.log + # The record reformer is used is discard the var.log.containers prefix and + # the Docker container ID suffix and "kubernetes." is pre-pended giving the tag: + # kubernetes.synthetic-logger-0.25lps-pod_default-synth-lgr + # Tag is then parsed by google_cloud plugin and translated to the metadata, + # visible in the log viewer + + # Example: + # {"log":"[info:2016-02-16T16:04:05.930-08:00] Some log text here\n","stream":"stdout","time":"2016-02-17T00:04:05.931087621Z"} + + type tail + format json + time_key time + path /var/log/containers/*.log + pos_file /var/log/gcp-containers.log.pos + time_format %Y-%m-%dT%H:%M:%S.%N%Z + tag reform.* + read_from_head true + + + + type parser + format /^(?\w)(? + + + type record_reformer + enable_ruby true + tag raw.kubernetes.${tag_suffix[4].split('-')[0..-2].join('-')} + + + # Detect exceptions in the log output and forward them as one log entry. + + @type copy + + + @type prometheus + + + type counter + name logging_line_count + desc Total number of lines generated by application containers + + tag ${tag} + + + + + @type detect_exceptions + + remove_tag_prefix raw + message log + stream stream + multiline_flush_interval 5 + max_bytes 500000 + max_lines 1000 + + + system.input.conf: |- + # Example: + # Dec 21 23:17:22 gke-foo-1-1-4b5cbd14-node-4eoj startupscript: Finished running startup script /var/run/google.startup.script + + type tail + format syslog + path /var/log/startupscript.log + pos_file /var/log/gcp-startupscript.log.pos + tag startupscript + + + # Examples: + # time="2016-02-04T06:51:03.053580605Z" level=info msg="GET /containers/json" + # time="2016-02-04T07:53:57.505612354Z" level=error msg="HTTP Error" err="No such image: -f" statusCode=404 + + type tail + format /^time="(?