12 Temmuz 2022 Salı

nfs Volume

Giriş
Network-Attached Storage(NAS) kavramına bakmak lazım. Açıklaması şöyle. Yani NAS kendi işlemcisi, işletim sistemi olan müstakil bir bilgisayar gibi.
Have you ever wondered how businesses shared files and data across computers within a network in the 1980s? They relied on network-attached storage(NAS) - a reliable and efficient way to deliver unstructured data to the network-connected devices using an ethernet connection.

With time, different technologies have become prominent, including cloud storage offering cheap online storage. However, NAS still solves the critical business pain point of intuitively sharing files within an organization.
Kullanılan protokoller şöyle
NAS box supports various protocols for file formatting transferred across the network. These include:
Network File System(NFS)
- Server Message Blocks(SMB)
- Apple Filing Protocol(AFP)
- Internetwork Packet Exchange
- Common Internet File System(CIFS)
- NetBIOS Extended User Interface
Kullanım
1. Podda kullanmak için volumes ile direkt yüklenebilir. Bu durumda nfs sunucusunun IP adresini belirtmek gerekir.
2. Podda kullanmak için PersistentVolumeClaim ile isim belirtilir

1. Volume Olarak Direkt Kullanma
Örnek
Şöyle yaparız
#Pod definiton with nfs share directory
apiVersion: v1
kind: Pod
metadata:
  name: webserver
spec:
  containers:
  - image: nginx:latest
    name: nginx-container
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: test-vol
  volumes:
  - name: test-vol
    nfs:
      server: 10.3.97.250           # nfs server ip or dns
      path: /var/local/nfs-share    # nfs share directory
2. NFS'i PersistentVolume Olarak Yaratma
Örnek
Şöyle yaparız
#PV using NFS-Share directory
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /var/nfs_server/kubernetes_data
    server: 10.25.96.6     #IP or DNS of nfs server
Örnek
PersistentVolume yaratılır. Şöyle yaparız
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: any-name
  nfs:
    path: /test
    server: 10.0.0.0
PersistentVolumeClaim yaratılır. Şöyle yaparız
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 10Gi
  storageClassName: any-name
Pod'da kullanmak için şöyle yaparız
apiVersion: v1
kind: Pod
metadata:
 name: pod-with-volume
spec:
 containers:
 - image: nginx
   name: pod-with-volume
   volumeMounts:
   - mountPath: /data
     name: my-volume
 volumes:
 - name: my-volume
   persistentVolumeClaim:
     claimName: my-pvc



azure Volume

Giriş 
Açıklaması şöyle
AWS/AKS/GKE and other cloud providers provide storage to be used by their managed Kubernetes services.
Örnek
Şöyle yaparız
apiVersion: v1
kind: Pod
metadata:
 name: azure-volume
spec:
 containers:
  - image: httpd
    name: azure-volume
    volumeMounts:
      - name: azureVolume
        mountPath: /mnt/azure
 volumes:
      - name: azure
        azureDisk:
          diskName: my-test.vhd
          diskURI: https://my.blob.com/vhd/my-test.vhd
Açıklaması şöyle
In the above specification, 
- diskName : Name of the VHD blob object
- diskURI : URI of the VHD blob

emptyDir Volume - Pod Silinince Bu Volume da Silinir

Giriş
Açıklaması şöyle. emptyDir volume Java'da temporary dosya, dizin yaratmak için idealdir.
This kind of Volume is created when a Pod is scheduled on a node. This volume is for the lifetime of the pod only. It gets deleted as soon as pod is terminated. All containers within the Pod share this volume. The use case for such a volume can be to use as a temporary space for applications internal work or use as a cache for improving the performance of applications. 
1. Pod içindeki tüm container'lar bu volume'a erişebilir. 
2. Pod başlarken bu dizin boştur
3. Pod silinince bu dizin de silinir
4. Eğer container çökerse bu dizin ve içindekiler kaybolmaz. Açıklaması şöyle
A container crashing does not remove a Pod from a node. The data in an emptyDir volume is safe across container crashes.
medium Alanı
Açıklaması şöyle
What type of storage medium should back this directory. The default is "" which means to use the node's default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir
sizeLimit Alanı
Açıklaması şöyle
Total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir

Kullanım
1. volumes bölümünde -name ile bir volume ismi belirtilir.
2. Bu volume için emptyDir belirtilir
3. İstenirse emptyDir bellekte te olabilir

Örnek - memory
Şöyle yaparız
apiVersion: v1
kind: Pod
metadata:
  name: my-server
spec:
  containers:
  - image: nginx
    name: my-server
    volumeMounts:
    - mountPath: /testcache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      medium: Memory
Örnek - TMP
Açıklaması şöyle
If you need to write temporary/cache files, fine, but since you are going to lose everything when that container dies, you shouldn't be writing anything of import within a container. Since you are only going to write temporary files, you really don't need your container to have a writable layer. Just mount a volume at /tmp and run your container with a read-only root file system. 
Şöyle yaparız. Burada tmp isimli emptyDir volume /tmp dizini olarak kullanılıyor. Ayrıca Linux'taki TMP ortam değişkeni de /tmp dizinine yönlendiriliyor.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app
      name: app
    spec:
      containers:
      - env:
        - name: TMPDIR
          value: /tmp
        image: my/app:1.0.0
        name: app
        securityContext:
          readOnlyRootFilesystem: true
        volumeMounts:
        - mountPath: /tmp
          name: tmp
      volumes:
      - emptyDir: {}
        name: tmp
Örnek
Şöyle yaparız. Burada "grafana-storage" isimli volumeMounts bir emptyDir Volume'a atıfta bulunuyor.
grafana-datasources  isimli volumeMounts ile bir ConfigMap'e atıfta bulunuyor
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: monitoring
spec:
  ...
  template:
    ...
    spec:
      containers:
      - name: grafana
        ...
        resources:
          ...
        volumeMounts:
          - mountPath: /var/lib/grafana
            name: grafana-storage
          - mountPath: /etc/grafana/provisioning/datasources
            name: grafana-datasources
            readOnly: false
      volumes:
        - name: grafana-storage
          emptyDir: {}
        - name: grafana-datasources
          configMap:
              defaultMode: 420
              name: grafana-datasources

Kubernetes Storage Tipleri

Giriş
Seçenekler şöyle
1. Volumes
2. Persistent Volume
3. Dynamic Volumes

Volumes
Açıklaması şöyle
Kubernetes Volume is a directory on a disk backed by some media. This Volume is available to all containers running inside a Pod. The Pod specification mentions what kind of volume is to be provisioned and where to mount it. The kind of Volume is specified by choosing one between many Volume Types that Kubernetes provides. Some of these are:

- AWS EBS
- Azure Disk
- Ceph file system- emptyDir
- nfs
- secret
Persistent Volume
Bizim tarafımızdan devreye alınır

Dynamic Volumes
Otomatik yaratılır

4 Temmuz 2022 Pazartesi

Kubernetes API Server - Dışarıdan Gelen İsteği Doğrular

Giriş
API Server master node üzerinde çalışır. Açıklaması şöyle
How can Kubernetes APIs be secured?

Kubernetes API security approaches include:

- Use the correct authorization mode with the API server
- Use API authentication
- Ensure that TLS protects all incoming traffic
- Use authorization-mode=Webhook to make kubeless protect the API
- Use restrictive RBAC role policy on the kube-dashboard
- Remove any default service account permissions
Açıklaması şöyle. Dışarıdan herhangi bir istek geldiğinde API server doğrulama yapar. Ayrıca etcd ile etkileşimde bulunan tek bileşen budur
The API Server provides APIs to support lifecycle orchestration (scaling, updates, and so on) for different types of applications. It also acts as the gateway to the cluster, so the API server must be accessible by clients from outside the cluster.
1. "kubectl komutu" API Server ile REST çağrısı kullanarak haberleşir. Şeklen şöyle

2. API Server aldığı yaml içeriğini etcd sunucusuna kaydeder. Tüm akış şöyle
1. User declares what he/she wants and passes that to K8S using kubectl command. We all know that API-Server is the only component that can talk to user, master node other components and worker nodes.
2. kubectl interacts with API-Server and generates a manifest (we can say a description of user wants).
3. This manifest is written in ETCD (key-value database and single source of truth) by API-Server.
4. As soon as there is something in ETCD, controller manager wakes up and respond according to the requirement. For deployment, a Deployment controller wakes up and check the requirement. It says replica is needed so, it’ll create a replica set (a bunch of item that goes into the pods) and goes to sleep. 
5. Now, the controller responsible for replica take its turn and create 3 replicas of pod. The pods details get stored in ETCD.
6. Schedular wakes up and sees that there are pending pods without any nodes assigned. So, it will assign the nodes and goes to sleep.
7. kubelet (on worker node) asks API-Server whether it has something for them? Now nodes has been assigned to pods kubelet will pull the image, networking and response back to API-Server that pods are running and API-Server writes the update to ETCD.



API Server Bileşenleri
1. HTTP Module
Açıklaması şöyle
1. This is nothing more than a regular web server.
2. Once the API receives the requests, it has to make sure that:
 - You have access to the cluster (authentication).
- You can create, delete, list, etc. resources (authorization).
3. This is the part where the RBAC rules are evaluated.
2. Mutation Admission Controller Module
Açıklaması şöyle
This component is in charge of looking at your YAML and modifying it.

Does your Pod have an image pull policy?

- If not, the admission controller will add “Always” for you.

Is the resource a Pod?
 -It sets the default Service Account (if none is set).
- Adds a volume with the token.

And more!
3. Validation Admission Controller Module
Açıklaması şöyle. Yani bazı mantıksal kontroller yapılıyor
Are you trying to deploy more resources than your quota?

The controller will prevent that too.
Kubernetes API Server Extension Points
 Mutation Admission Controller ve Validation Admission Controller noktalarına hook veya extension takılabiliyor. Şeklen şöyle.
Istio ve GateKeeper şeklen şöyle

Metrics API
Açıklaması şöyle
You can add your own APIs and register them with Kubernetes.

An excellent example of that is the metrics API server.

The metrics API server registers itself with the API and exposes extra API endpoints.
Şeklen şöyle














23 Haziran 2022 Perşembe

kubectl wait seçeneği

Giriş
--for condition = available deployment şeklinde kullanılır

Örnek
Şöyle yaparız
# Add the Repo
helm repo add datawire https://app.getambassador.io helm repo update # Create Namespace kubectl create namespace emissary && \ kubectl apply -f https://app.getambassador.io/yaml/emissary/2.2.2/emissary-crds.yaml kubectl wait --timeout=90s --for=condition=available deployment emissary-apiext \ -n emissary-system # Install helm install emissary-ingress --namespace emissary datawire/emissary-ingress && \ kubectl -n emissary wait --for condition=available --timeout=90s deploy \ -lapp.kubernetes.io/instance=emissary-ingress

3 Haziran 2022 Cuma

Kubernetes kind : Deployment

Giriş
Bu yaml yerine kubectl create deployment komutu kullanılabilir.
Deployment'ı geri almak için kubectl rollout undo  komutu kullanılabilir.

Deployment Nedir
Açıklaması şöyle. Yani kaç tane pod istediğimizi vs belirtiriz.
Although pods are the basic unit of computation in Kubernetes, they are not typically directly launched on a cluster. Instead, pods are usually managed by one more layer of abstraction: the deployment.

A deployment’s primary purpose is to declare how many replicas of a pod should be running at a time. When a deployment is added to the cluster, it will automatically spin up the requested number of pods, and then monitor them. If a pod dies, the deployment will automatically re-create it.

Using a deployment, you don’t have to deal with pods manually. You can just declare the desired state of the system, and it will be managed for you automatically.
Deployment Ne Zaman Değişmiş Kabul Edilir
Açıklaması şöyle
A Deployment’s rollout is triggered if and only if the Deployment’s pod template (i.e, .spec.template) is modified. If you modify the scaling parameter, it will not rollout, but if you are changing the deployment labels or container images info, it will trigger the deployment rollout to update it.

kind : Deployment vs kind : Pod
Deployment kullanılırsa, eğer pod kapanırsa tekrar başlatılır. Pod kullanılırsa tekrar başlatılmaz. Kubernetes kind : Pod yazısına bakabilirsiniz.

Deployment Name Uzunluğu
metadata/name altınındaki string uzunluğu en fazla 47 karakter olsa iyi olur. Açıklaması şöyle. Yani aslında 253 karaktere kadar deployment name olabiliyor.
Most Kubernetes objects, including Deployments, can have names that are ≤ 253 characters in length. You should, however, consider restricting your Deployment names to ≤ 47 characters because of the implications that exceeding this threshold will have on your Pod names.
Sebebi şöyle. Yani deployment name kullanılarak ReplicaSet ve ondan da Pod ismi türetiliyor.
As you likely know, Deployments create ReplicaSets — and those ReplicaSets create Pods. When Deployment names are short (e.g. mydeployment), the ReplicaSet name is the Deployment name with a suffix of a dash/hyphen followed by the pod-template-hash, which is 9 hexadecimal characters (e.g. mydeployment–548f955bf). The Pod name is the ReplicaSet name with a suffix of a dash/hyphen followed by 5 random hexadecimal characters (e.g. mydeployment–548f955bf-j8wng).

This is convenient because it allows you to easily see which Pods correspond to which ReplicaSets as well as which Deployments simply by looking at their names, while at the same time guaranteeing uniqueness of both the Pod and ReplicaSet names.
Eğer deployment ismi 47 karakterden fazlaysa ReplicaSet ve Pod isimleri de kırpılmaya başlıyor.

spec/containers Alanı
spec/containers içinde tüm container'lar tanımlanabiliyor. Aynı şey "kind : Pod" içinde de yapılabiliyor
Örnek
Şöyle yaparız. 4 replica içren nginx çalıştırılıyor
apiVersion: v1
kind: Service metadata: name: my-nginx-svc labels: app: nginx spec: type: LoadBalancer ports: - port: 80 selector: app: nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx labels: app: nginx spec: replicas: 4 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
Örnek
Şöyle yaparız. Burada container için env de tanımlanıyor
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-deployment
  namespace: default
  labels:
    app: order-deployment
spec:
  selector:
    matchLabels:
      app: order-deployment
  template:
    metadata:
      labels:
        app: order-deployment
    spec:
      containers:
        - name: order-service
          image: europe-west4-docker.pkg.dev/...
          env:
            - name: SPRING_DATASOURCE_URL
              value: "jdbc:postgresql://postgres-service:5432/postgres?currentSchema=order
          resources:
            limits:
              cpu: "500m"
              memory: "1024Mi"
            requests:
              cpu: "200m"
              memory: "256Mi"
Örnek
Şöyle yaparız. Burada container için command tanımlanıyor
apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-deployment-name
spec:
  replicas: 1
  selector:
    matchLabels:
      app: your-app-name
  template:
    metadata:
      labels:
        app: your-app-name
    spec:
      containers:
      - name: your-container-name
        image: your-image-name
        command: ["./your-executable-name","-Djavax.net.ssl.trustStore=/opt/certs/truststore.jks","-Djavax.net.ssl.trustStorePassword=changeit"]
        ports:
        - containerPort: 9092
spec/containers/resources Alanı
Kubernetes Resource Requirements yazısına taşıdım

.spec.minReadySeconds = 30
Açıklaması şöyle
The Kubernetes deployment specification allows us to set a minimum amount of time that a new pod must be in the ready state before it starts terminating the old pod. 

spec/selector/matchLabesl Alanı
matchLabels Alanı yazısına taşıdım

spec/restartPolicy Alanı
Açıklaması şöyle
Always means that the container will be restarted even if it exited with a zero exit code (i.e. successfully). This is useful when you don't care why the container exited, you just want to make sure that it is always running (e.g. a web server). This is the default.

OnFailure means that the container will only be restarted if it exited with a non-zero exit code (i.e. something went wrong). This is useful when you want accomplish a certain task with the pod, and ensure that it completes successfully - if it doesn't it will be restarted until it does.

Never means that the container will not be restarted regardless of why it exited.
Örnek
Şöyle yaparız. Burada Kafka sunucusunun sürekli çalışması istendiği için "restartPolicy: Always" kullanılıyor
kind: Deployment
apiVersion: apps/v1
metadata:
  name: example-kafka
  namespace: kafka-example
  labels:
    app: example-kafka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example-kafka
  template:
    metadata:
      labels:
        app: example-kafka
    spec:
      containers:
        - name: example-kafka
          image: 'wurstmeister/kafka:2.12-2.4.0'
          ports:
            - containerPort: 9093
              protocol: TCP
            - containerPort: 9092
              protocol: TCP
          env:
            - name: KAFKA_ADVERTISED_LISTENERS
              value: INTERNAL://:9092,EXTERNAL://example-kafka.kafka-example.svc.cluster.local:9093
            - name: KAFKA_CREATE_TOPICS
              value: example-topic:1:1
            - name: KAFKA_INTER_BROKER_LISTENER_NAME
              value: INTERNAL
            - name: KAFKA_LISTENERS
              value: INTERNAL://:9092,EXTERNAL://:9093
            - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
              value: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
            - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR
              value: '1'
            - name: KAFKA_ZOOKEEPER_CONNECT
              value: example-zookeeper.kafka-example.svc.cluster.local:2181
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
      dnsPolicy: ClusterFirst
      schedulerName: default-scheduler
      enableServiceLinks: true
  strategy:
    type: RollingUpdate

Strategy Alanı
Deployment Strategy yazısına taşıdım

imagePullPolicy Alanı
IfNotPresent değerini alabilir. Şöyle yaparız
apiVersion: apps/v1
kind: Deployment # Kubernetes resource kind we are creating
metadata:
 name: spring-boot-k8s
spec:
 selector:
   matchLabels:
     app: spring-boot-k8s
 replicas: 2 # Number of replicas that will be created for this deployment
 template:
   metadata:
     labels:
       app: spring-boot-k8s
 spec:
   containers:
      — name: spring-boot-k8s
        image: springboot-k8s-example:1.0 
           # Image that will be used to containers in the cluster
           imagePullPolicy: IfNotPresent
        ports:
          — containerPort: 8080 
          # The port that the container is running on in the cluster
terminationGracePeriodSeconds Alanı
terminationGracePeriodSeconds alanı yazısına taşıdım

Kubernetes 1.33 - Octarine

Giriş Yenilikler şöyle 1. Native Sidecar Containers 2. In-Place Pod Resizing: The End of Disruptive Scaling Artık pod'un belleğini çalış...