Kubernetes Kurulumu
Merhaba arkadaşlar, bir önceki yazımızda Kubernetes kurulumu için birtakım yollar ve adımlardan bahsetmiştik. Bu laboratuvarda kubeadm kullanarak kubernetes cluster kurulumu gerçekleştireceğiz. Kubernetes kullanan topluluklar arasında bağımsız bir araç olması sebebiyle kubernetes cluster kurmak için birincil yöntem olması gerektiği vurgulanmaktadır.
kubeadm komutunu kullanırken uyarı veya hata olarak bazı gereksinimler karşınıza çıkabilir. Çoğu komutlar normal kullanıcılar tarafından çalıştırılırken bazıları için root ayrıcalıklarını kullanmamız gerekecek. GCP yada AWS gibi uzaktan erişim noktalarından erişiyorsanız Linux makinenize uzaktan erişim sağlamak için PuTTy gibi bir SSH istemcisi kullanmanız gerekecektir. Ayrıca varsa SSH anahtarını yüklemeyi unutmayalım.
Kubernetes öğrenirken Linux makinenizde güvenlik duvarını devre dışı bırakın. Bileşenler arası iletişim için gerekli bağlantı noktaları için bu önemli olacaktır. GCP kullanıyorsanız tüm trafiğin tüm portlardan akacak şekilde ayarlamayı unutmayın (allows all traffic to all ports). VirtualBox kullanıyorsanız VM’ler arası ağ ağlantısının promiscuous modda olduğundan emin olmalıyız.
Benim burada kullanmış olduğum Linux makine GCP üzerinde bulunmaktadır ve bahsettiğim tüm ayarlar yapılmış durumdadur. Ubuntu 16.04 versiyonunu kurulu. 2 vCPU ve 7.5 GB memory’si bulunmaktadır.
Kuruluma başlayalım.
PuTTy gibi SSH istemcisi kullanarak yada VirtualBox ile linux makinemize bağlandıktan sonra aşağıdaki komutları çalıştırıp güncelleme yaptırıyoruz.
$ sudo -i
# apt-get update && apt-get upgrade -y
Bir container ortami için ana seçeneğimiz Docker’dır. Aşağıdaki komutu çalıştırarak Docker kurulumu yapabilirsiniz.
# apt-get install -y docker.io
Linux makinemiz için kubernetes deposu oluşturalım. Benim kullandığım makine Ubuntu 16.04 olduğu için kubernetes-xenial kelimesini main anahtar kelimesi ile ekliyorum.
# vim /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main # ekleyeceğimiz satır.
Paketimiz için bir GPG anahtarı ekliyoruz.
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
OK # alacağımız çıktı.
Yeni eklediğimiz depo ile birlikte yeni güncelleştirmeleri alalım.
# apt-get update
Artık kubeadm, kubelet ve kubectl yazılımlarımızı indirebileceğimiz duruma geldik.
# apt-get install -y kubeadm kubelet kubectl
Container Networking Interface (CNI) için hangi pod ağının kullanılacağına karar vermek için cluster içindeki beklenen talepler dikkate alınmalıdır. Cluster başına bir pod ağı olabilir. Ağ, container’dan container’a, pod’dan pod’a, pod’dan servise ve harici servis dışı iletişime izin vermelidir.
Calico adında bir ağ eklentisi kullanacağız. Şuan mevcutta bulunan Calico CNI kullanarak konuşlandırılmıyor. Calico’nun versiyonları RBAC ile esneklik için birden fazla yapılandırma dosyasına sahiptir. URL’ler uzun olduğu için yapılandırma dosyalarını kısaltılmış link üzerinden indireceğiz. Calico projesini buradan inceleyebilirsiniz.
# wget https://tinyurl.com/yb4xturm -O rbac-kdd.yaml
# wget https://tinyurl.com/y8lvqc9g -O calico.yaml
İndirmiş olduğumuz Calico dosyasını less komutu ile açtığımız zaman içerisinde CALICO_IPV4POOL_CIDR değerinin “192.168.0.0/16” olduğunu görürüz burda bu değer ile birlikte kubeadm komutuna vereceğimiz değeri aynı olduğuna dikkat edip kubernetes cluster kurulumunu başlatmalıyız.
# kubeadm init --kubernetes-version 1.14.0 --pod-network-cidr 192.168.0.0/16 | tee kubeadm-init.out
Adım adım kodları açıklamak gerekirse;
- kubeadm init => Cluster oluşturur.
- –kubernetes-version => kullanacağımız (indirmiş olduğumuz) kubernetes versiyonunu girip kuruluma bu versiyon üstünden devam ettirir.
- –pod-netword-cidr => IP aralığımız, Calico dosyasının içerisindeki değerin aynısını yazdık
- tee kubeadm-init.out => Çıktıları kayıt ettirir
Kurulum, aşağıdaki gibi bir çıktı verir ve kurulumdan sonra yapılandırma için komutlar önerir.
[init] using Kubernetes version: v1.14.0
[preflight] running pre-flight checks
[preflight/images] Pulling images required for setting up aKubernetes cluster
[preflight/images] This might take a minute or two, dependingon the speed of your internet connection
.
.
.
Your Kubernetes master has initialized successfully!
To start using your cluster, you need to run the following asa regular user:
mkdir -p $HOME/.kubesudo
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.Run "kubectl apply -f [podnetwork].yaml" with one of the optionslisted at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the followingon each node as root:
kubeadm join 10.128.0.2:6443 --token bsy76u.xbfuzztjytp42ftk \
--discovery-token-ca-cert-hash sha256:f7ba5d86cc2cd4c8d5038763c351bcea74d2f18ae10f5def27ba846be6f9b89c
Kurulum tamamlandıktan sonra bize önermiş olduğu yapılandırma işlemlerini tamamlayalım.
# exit
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
$ less .kube/config => kurulumu kontrol edebilirsiniz.
Ağ eklenti yapılandırmasını cluster’ınıza uygulayın. Dosyayı önce geçerli kullanıcınıza (root olmayan) kopyalamayı unutmayın.
$ sudo cp /root/rbac-kdd.yaml .
$ kubectl apply -f rbac-kdd.yaml
$ sudo cp /root/calico.yaml .
$ kubectl apply -f calico.yaml
Cluster’ı Büyütelim
Mevcutta kullanmış olduğunuz Kubernetes Cluster’ını büyütmek için aynı platformda (benim kullanmış olduğum GCP) bir VM daha oluşturuyoruz. Oluşturduğumuz VM’i üst kısımdaki kuruluma benzer bir şekilde devam ettircez. Oluşturulan VM için aynı SSH anahtarını kullanabilirsiniz.
$ sudo -i
# apt-get update && apt-get upgrade -y
# apt-get install -y docker.io
# vim /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main => ekleyeceğimiz satır.
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
OK => alacağımız çıktı.
# apt-get update
# apt-get install -y kubeadm kubelet kubectl
# exit
Bu işlemleri worker node’unuza uyguladıktan sonra master node’unuzun IP adresini öğrenelim. Arabirim adı node’un çalıştığı yere göre farklılıklar gösterecektir. GCP içerisinde şuanda bu node türü için arabirim ens4’tür.
(master node)$ ip addr show ens4 | grep inet
inet 10.128.0.2/32 brd 10.128.0.2 scope global ens4
inet6 fe80::4001:aff:fe8e:e/64 scope link
Bu aşamada join komutunu master node’umuza uyguluyoruz. Master node’daki token’ı bulalım. Bu token varsayılan olarak 24 saat geçerlidir. Eğer süre geçtiye ve yeni bir tane oluşturmak isitiyorsanız kubeadm token create komutunu kullanabilirsiniz. Token’ları listelemek için ise kubeadm token list komutunu kullanabilirsiniz.
(master node)$ sudo kubeadm token list
TOKEN TTL EXPIRES 39fmdo.p3ia1beow1tsybwy 23h 2019-04-09T13:27:33Z
Token’ın süresi geçtiyse TTL kısmında invalid yazar. Yeni token oluşturmak için aşağıdaki komutu kullanabilirsiniz.
(master node)$ sudo kubeadm token create
39fmdo.p3ia1beow1tsybwy
Kubernetes 1.9 versiyonundan itibaren master node’e node’ların güvenli bir şekilde bağlanması için Discovery Token CA Cert Hash oluşturmalı ve kullanmalısınız. Aşağıdaki komutu master node’da çalıştırıp bu işlemi yapabilirsiniz.
(master node)$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
f7ba5d86cc2cd4c8d5038763c351bcea74d2f18ae10f5def27ba846be6f9b89c
Bu durumdan itibaren artık worker node’u master node’a ekleyebiliriz. Aşağıdaki komutları worker node’da çalıştırın. Edindiğimiz bilgileri parametre olarak vermeyi unutmayalım.
(worker node)# kubeadm join --token 39fmdo.p3ia1beow1tsybwy 10.128.0.2:6443 --discovery-token-ca-cert-hash sha256:f7ba5d86cc2cd4c8d5038763c351bcea74d2f18ae10f5def27ba846be6f9b89c
# exit
$ kubectl get nodes
The connection to the server localhost:8080 was refused- did you specify the right host or port?
Artık yeni oluşturduğumuz node’u master node’a bağladık. Master node’da aşağıdaki komutu çalıştırırsanız iki tane node olduğunu görebilirsiniz.
(master-node)$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-vm Ready master 27h v1.14.0
k8s-vm2 NotReady <none> 19s v1.14.0
Yalnız burda şunu unutmamamız gerekiyor. Worker node içerisinde kubectl get nodes komutunu çalıştırdığımızda çalışmadığını görürüz. Bunun sebebi worker node içerisinde ./kube/config yapılandırması olmamasıdır. Buna ihtiyacımız yok zaten worker node’umuzu master node üzerinden yöneteceğiz.
(worker-node)$ kubectl get nodes
The connection to the server localhost:8080 was refused - did you specify the right host or port?
Node içerisinde taint tanımlı olabilmektedir. Taint konusunu ileriki eğitim yazılarımızda göreceğiz. Burda sadece bunu kaldıracağız. Şimdi bu taint’lere bakalım ve ortadan kaldıralım.
$ kubectl describe node | grep -i taint
Taints: node-role.kubernetes.io/master:NoSchedule
Taints: <none>
$ kubectl taint nodes --all node-role.kubernetes.io/master-
node/master-node-1 untainted
error: taint "node-role.kubernetes.io/master:" not foun
Basit Bir Uygulama Dağıtalım
Şimdi oluşturduğumuz ortamı test edebiliriz. Bunun için nginx web server kurulumu yapalım. Bir uygulamayı bir container’da dağıtıp izleyelim. (Kafa karışmasını önlemek adına aşağıdaki kodları master node’da yazıyoruz.)
$ kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 38s
Eğer bir deployment’ın detaylarını görüntülemek istiyorsak describe komutunu kullanırız.
$ kubectl describe deployment nginx
ment nginx
Name: nginx
Namespace: default
CreationTimestamp: Mon, 08 Apr 2019 13:53:18 +0000
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=nginx
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0
....
Oluşturulmuş bir dağıtımın(deployment) YAML formatını görmek istiyorsan -o yaml parametresini kullanabiliriz.
$ kubectl get deployment nginx -o yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2019-04-08T13:53:18Z"
generation: 1
labels:
app: nginx
name: nginx
....
YAML çıktısını bir dosyaya kayıt edelim.
$ kubectl get deployment nginx -o yaml > ornek.yaml
Şimdi oluşturduğumzu dağıtımı silip, elimizde bulunan YAML dosyasından bir dağıtım oluşturalım.
$ kubectl delete deployment nginx
deployment.extensions "nginx" deleted
$ kubectl create -f ornek.yaml
deployment.extension/nginx created
Nesne oluşturmadan ham YAML veya JSON çıktısını almak için –dry-run parametresini kullanabiliriz. Bu parametre nesne oluşturmaz, sadece oluşturuyormuş gibi yapar.
$ kubectl create deployment two --image=nginx --dry-run -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: two
name: two
....
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 1/1 1 1 19m
Şuanda bir container içerisinde konuşlandırılmış bir nginx web sunucumuz mevcuttur. Bu web sunucusunun giriş sayfasına ulaşmak için bizim servislere ihtiyacımız vardır. Bir uygulamanın içerisinde servis çıkarmak istiyorsak expose komutunu kullanırız. Daha fazla ayrıntı için expose -h komutunu çalıştırabilirsiniz.
$ kubectl expose deployment/nginx
error: couldn't find port via --port flag or introspection
See 'kubectl expose -h' for help and examples
Servisi çalıştırmak istediğimizde bu hata ile karşılaşmamız çok normal bir durum. Çünkü container’ı biz direk olarak deploy ettik. Dolayısıyla container için bir port ve protocol belirlemedik. Bunun için daha önceden oluşturduğumuz nginx YAML dosyasını açalım ve container’a port ve protocol belirleyelim. Ardından dağıtılmış olan container ile replace edelim.
$ vim ornek.yaml
....
spec:
containers:
- image: nginx
name: nginx
ports: # ekledik
- containerPort: 80 # ekledik
protocol: TCP # ekledik
resources: {}
....
$ kubectl replace -f ornek.yaml
deployment.apps/nginx replaced
Pod ve deployment’ları aynı anda listelemek için virgül ile ayırabilirsiniz.
$ kubectl get deploy,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.extensions/nginx 1/1 1 1 2m54s
NAME READY STATUS RESTARTS AGE
pod/nginx-56db997f77-x582m 1/1 Running 0 2m54s
Şimdi nginx dağıtımı içerisindeki servisimizi çalıştırabiliriz.
$ kubectl expose deployment/nginx
service/nginx exposed
nginx dağıtımımız üzerinden oluşturduğumuz servisi aşağıdaki komut ile bilgilerini görebilir ve listeleyebiliriz. Aşağıdan servis yapılandırmasını doğrulayabiliriz. Listedeki Cluster-IP bizim endpoint’imiz değildir. Calico kubelet ve kube-proxy tarafından Cluster-IP’sinin Endpoint’e işlemesini sağlar. Aşağıda Endpoint’in IP’sine bakarak bunu anlayabiliriz.
$ kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.106.116.194 <none> 80/TCP 91s
$ kubectl get ep nginx
NAME ENDPOINTS AGE
nginx 192.168.1.4:80 3m25s
Pod’umuzun hangi Node’da çalıştığını öğrenelim.
$ kubectl describe pod nginx-56db997f77-x582m | grep Node:
Node: k8s-vm2/10.142.0.15 => 2. node(worker node'umuz)
curl komutu ile nginx başlangıç sayfasına bağlanalım. Bakalım herşey yolunda gitmiş mi 🙂
$ curl 10.106.116.194:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
....
Şimdi uygulamamızı scale edelim. Web sunucumuzu bir taneden üç taneye çıkaralım.
$ kubectl scale deployment nginx --replicas=3
deployment.extensions/nginx scaled
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 3/3 3 3 20m
Endpoint’lerimize bakalım. Onlarda nasıl bir değişiklik olmuş.
$ kubectl get ep nginx
NAME ENDPOINTS AGE
nginx 192.168.1.4:80,192.168.1.5:80,192.168.1.6:80 18m
Bir pod silindiği zaman ReplicaSet controller’ı tarafından yeni bir pod hemen dağıtılır. Bunun denemesini şöyle yapabiliriz.
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP
nginx-56db997f77-6vszn 1/1 Running 0 5m24s 192.168.1.6
nginx-56db997f77-n9n9p 1/1 Running 0 5m24s 192.168.1.5
nginx-56db997f77-x582m 1/1 Running 0 24m 192.168.1.4
$ kubectl delete po nginx-56db997f77-6vszn
pod "nginx-56db997f77-6vszn" deleted
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP
nginx-56db997f77-57rgw 1/1 Running 0 71s 192.168.1.7
nginx-56db997f77-n9n9p 1/1 Running 0 7m44s 192.168.1.5
nginx-56db997f77-x582m 1/1 Running 0 26m 192.168.1.4
$ kubectl get ep nginx
NAME ENDPOINTS AGE
nginx 192.168.1.4:80,192.168.1.5:80,192.168.1.7:80 23m
Sonuç itibariyle ReplicaSet kullanarak scale ettiğimiz zaman bir pod silindiğinde yerine bizim ayarlamış olduğumuz adet(3) sağlanacak kadar pod dağıtılır. Bu pod’lara yeni IP’ler atanır. Ve bu pod’un sağladığı endpoint değişmiş olur. Ama sonuçta bir nginx’e ClusterIP ile eriştiğimiz için arkada tarafta olan (yıkılan ve yeniden dağıtılan pod) işlemler bizim için kesinti oluşturmaz.
Cluster Dışından Erişim Sağlayalım
exec komutu ile pod’un içerisine erişebilirsiniz. print-env komutunu kullanarak pod’un içerisindeki ortam değişkenlerini yazdırabilirsiniz.
$ kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-56db997f77-57rgw 1/1 Running 0 6m44s
nginx-56db997f77-n9n9p 1/1 Running 0 13m
nginx-56db997f77-x582m 1/1 Running 0 32m
$ kubectl exec nginx-56db997f77-57rgw -- printenv | grep KUBERNETES
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
Daha önceden oluşturduğumuz nginx servisini silelim.
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28h
nginx ClusterIP 10.106.116.194 <none> 80/TCP 31m
$ kubectl delete svc nginx
service "nginx" deleted
Servisii yeniden dağıtalım ama bu sefer LoadBalancer olarak kuracağız. Servise bu sefer baktığımızda EXTERNAL_IP <none> değilde pending olarak görürüz. Bir sağlayıcı LoadBalancer’a yanıt vermediği sürece pending olarak gözükmeye devam eder.
$ kubectl expose deployment nginx --type=LoadBalancer
service/nginx exposed
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 29h
nginx LoadBalancer 10.101.110.55 <pending> 80:30339/TCP 19s
Linux makinemizin public IP adresini kullanarak kendi diz üstü bilgisayarınızın web tarayıcısı üzerinden artık nginx web sunucusuna erişebilirsiniz.
Kurulumları kaldıralım. Deployment’ı silmek Endpoint ve Service’leri silmek anlamına gelmiyor. Endpoint ve Service’leride kaldırdığımız deployment gibi kaldırmamız gerekiyor.
$ kubectl delete deployment nginx
deployment.extensions "nginx" deleted
$ kubectl delete ep nginx
endpoints "nginx" deleted
$ kubectl delete svc nginx
service "nginx" deleted
Kubernetes eğitiminin ilk eğitim laboratuvarını burada sonlandırmış oluyoruz. Bir sonraki konu başlığımız Kubernetes Mimarisi‘ni yakından inceleme fırsatımız olacak, görüşmek üzere !
Umarım bu yazı sizin için bilgilendirici olmuştur. Yazıyla ilgili bir sorunuz, görüşünüz veya isteğiniz varsa alt kısımda bulunan yorumlardan veya mail adresimden iletişime geçebilirsiniz. Bu yazının başkaları içinde bilgilendirici olduğunu düşünüyorsanız sosyal olun ve sosyal medyada paylaşın! Okuduğunuz için teşekkürler !!!!