התקנת קוברנטיס

לשם ההדגמה נעבוד עם 3 מכונות וירטואליות, לראשון נקרא k8node1, לשני k8node2 ולשלישי שהוא ישמש כמסטר שלנו נקרא k8master.
3 המכונות האלו מריצות CentOs7.

את הפקודות הבאות נריץ בכל אחת מהמכונותם שלנו. הפקודה הראשונה תהיה

sudo su

על מנת לקבל הרשאות ROOT.

לשם ההדגמה , אנו נבטל את SELinux – שימו לב, לא לעשות את זה בפרודקשיין, זה בשביל להקל על ההדגמה בלבד.

setenforce 0
sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

בשלב הבא אנו נפעיל את br_netfilter כדי לאפשר תקשורת בין הקלסטרים שלנו, הפקודה בעצם מאפשרת לקוברנטיס לבצע שינויים בIPTABLES.

modprobe br_netfilter
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables

בנוסף, אנו נבטל את הSWAP, הסיבה שאנו רוצים לעשות את זה היא על מנת שנקבל דיווח אמין על כמות הזיכרון שאנו משתמשים בו בפרודקשיין, כשאנו מאפשרים SWAP, הדיווח עלול להיות שגוי.

swapoff -a

בנוסף, אנחנו צריכים לערוך את הקובץ fstab, כצעד ראשון נבצע "גיבוי" לקובץ המקורי על ידי הפקודה:

cp /etc/fstab /etc/fstab.orig


ואז נריץ את הפקודה

nano /etc/fstab

ונוסיף # לפני השורה הבאה:

/root/swap swap swap sw 0 0

כך שנקבל את השורה הבאה במקום

#/root/swap swap swap sw 0 0

עכשיו נתקין את החבילות הדרושות לדוקר

 yum install -y yum-utils device-mapper-persistent-data lvm2

 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

 yum install -y docker-ce

בCENTOS אנו צריכים גם לוודא שדוקר וקוברנטיס ירוצו על אותו Cgroup Driver (הוא משמש לדיווח הסטטיסטיקה כמו זיכרון שאנו משתמשים בו וכו)
כמו כן, אנו נירצה שדוקר יופעל כל פעם שהמערכת מופעלת.

 sed -i '/^ExecStart/ s/$/ --exec-opt native.cgroupdriver=systemd/' /usr/lib/systemd/system/docker.service 

 systemctl daemon-reload

 systemctl enable docker --now

אחרי שסיימנו, נוספיף את הריפו של קוברנטיס על ידי הרצה של הפקודה הבאה:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
   https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

ומייד לאחר מכן נתקין

 yum install -y kubelet kubeadm kubectl

וכמובן לא נשכח להפעיל אותו

systemctl enable kubelet
systemctl start docker.service

שימו לב! את הפקודות הבאות נריץ רק בשרת המסטר שלנו

kubeadm init --pod-network-cidr=10.244.0.0/16

לאחר שנריץ את הפקודה הנל במסטר, נקבל בחזרה את הפקודה אותה נצטרך להריץ במכונות האחרות שלנו על מנת שהם יוכלו להצטרף לקלסטר שהמסטר שלנו מנהל, במיקרה שלי הפלט שהתקבל הוא:

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo 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 options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 172.31.37.95:6443 --token 9mplpv.oxlntc0gz9iukdm3 \
    --discovery-token-ca-cert-hash sha256:429959040fbf2743d9dc2ed67045548057ee2ae4781b5253143d8f93dca3bd0d 

והפקודה שחשוב שנשמור אותה היא למעשה הפקודה שמכילה את הטוקן שאנו צריכים כדי ששאר המכונות שלנו יוכלו להתחבר לקלסטר שיצרנו (למסטר)

kubeadm join 172.31.37.95:6443 --token 9mplpv.oxlntc0gz9iukdm3 \
    --discovery-token-ca-cert-hash sha256:429959040fbf2743d9dc2ed67045548057ee2ae4781b5253143d8f93dca3bd0d

לאחר שסיימנו נקיש exit כדי לצאת ממצב ROOT ונריץ את הפקודות הבאות:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

בנוסף נעשה דפלוי לפנל שלנו:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

ונבדוק את הסטטוס של הקלסטר על ידי הפקודה

kubectl get pods --all-namespaces

את הפקודות הנל אנו צריכים להריץ בכל המכונות שלנו (למעט הפקודות שקשורות למסטר בלבד). לאחר מכן בכל מכונה שהיא לא המסטר נריץ את הפקודה שמכילה את הטוקן שלנו (במקרה שלי)

kubeadm join 172.31.37.95:6443 --token 9mplpv.oxlntc0gz9iukdm3 \
    --discovery-token-ca-cert-hash sha256:429959040fbf2743d9dc2ed67045548057ee2ae4781b5253143d8f93dca3bd0d 

ולאחר מכן כשנריץ את הפקודה kubectk get nodes במסטר, אנו אמורים לראות את הנודים האחרים שלנו.

קצת על Kubernetes Deployments

Kubernetes Deployments הוא "כלי" שמאפשר לנו להפוך את תהליך יצירת הPODS שלנו לאוטומטי, אנו מגדירים את המצב (STATE) שאנו מעוניינים שהPOD שלנו יהיה בו, והקלסטר יידאג ליצור, לנהל ולשמור את המצב (STATE) שביקשנו.

דוגמאות לשימוש בDeployment

Scaling
מאפשר לבנו לבחור את מספר הרפליקציות שאנו מעוניינים שהDeployment ייצור לאפלקציה ספציפית. בנוסף ליצירת מס הרפלקציות שביקשנו, הDeployment יוודא שהרפלקציות שלנו יהיו מחולקות בצורה מאוזנת בין הNodes שלנו בשביל זמינות (Availability)

Self-Healing
כשאחד מהPODS שלנו נהרס,או נמחק בטעות, הDeployment ירים אחד חדש במקומו מיידית. אם הגדרתי שאני מעוניין ב6 רפליקציות למערכת שלי, ומחקתי בטעות רפליקה – הDeployment יידאג להרים רפליקה חדשה במקום.

Rolling Updates
בעזרת Deployment, אנו יכולים להחליף/לשנות IMAGE של קונטיינר, הDeployment יחליף קונטיינרים קיימים בגירסה החדשה בשלבים, הסיבה שאנו מעוניינים בכך היא שאם אנו נעשה דפלוי לאפלקציה החדשה שלנו בבת אחת – יהיה זמן מסויים של אי זמינות של המערכת, כאשר אנו עושים את הדפלוי בשלבים – החלפה של IMAGE בזה אחר זה אין לנו מצב של אי זמינות. כשיש לנו גירסה חדשה לאפלקציה שלנו ואנו רוצים לעשות לה דפלוי – אנו נעשה שימוש בDeployment.


הקובץ YAML הבא (נקרא לו example.yaml) למשל, מציין שאנו מעוניינים ב6 רפליקות, ובקונטיינר (במקרה שלנו קונטיינר אחד בלבד) בשם nginx שיריץ …nginx (במקרה שלנו 1.15.4).

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4
        ports:
        - containerPort: 80

כדי להפעיל את הדפלוימנט שיצרנו נריץ את הפקודה הבאה

kubectl create -f example.yaml

ונקבל בחזרה שורה שאומרת:
deployment.apps/nginx-deployment created

אחרי שהפעלנו את הדפלוימנט הזה נריץ את הפקודה הבאה כדי לראות את רשימת הדפלוימנט שלנו ונשים לב שנקבל פלט שמכיל את שם הדפלוימנט שלנו (nginx-deployment), את כמות הרפלקציות שביקשנו (Desired) שבמקרה שלנו הוא 6, ופרטים נוספים.

kubectl get deployments

ונקבל במיקרה שלי:

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 6 6 6 6 30s

כדי לקבל מידע נוסף על דפלוימנט ספציפי נריץ את הפקודה הבאה , שימו לב שהפקודה צריכה להכיל את שם הדפלוימנט שאנו מעוניינים לקבל מידע נוסף לגביו, במיקרה שלנו nginx-deployment

kubectl describe deployment nginx-deployment

ועכשיו אנו רואים פרטים מלאים, כמו פורטים, סוג הIMAGE וכו.

אגב, אם נריץ את הפקודה

kubectl get pods

במיקרה שלנו אנו ניראה שיש 6 PODS שרצים (כיון שביקשנו 6 רפליקות).

NAME READY STATUS RESTARTS AGE
nginx-deployment-d55b94fd-8qbrs 1/1 Running 0 100s
nginx-deployment-d55b94fd-9rc4t 1/1 Running 0 100s
nginx-deployment-d55b94fd-dj4lx 1/1 Running 0 100s
nginx-deployment-d55b94fd-g278x 1/1 Running 0 100s
nginx-deployment-d55b94fd-kp4v6 1/1 Running 0 100s
nginx-deployment-d55b94fd-pvq87 1/1 Running 0 100s


אם נמחוק אחד מהPOD שלנו , על ידי הפקודה
kubectl delete nginx-deployment-d55b94fd-8qbrs למשל
אנו ניראה שPOD חדש נוצר במקומו כמעט מיידית כיון שדרשנו שיהיו לנו 6 רפליקות.
ונוכיח את זה על ידי הרצת הפקודה kubectl get pods שוב, ובמיקרה שלי הפלט שהתקבל הוא

nginx-deployment-d55b94fd-9rc4t 1/1 Running 0 2m15s
nginx-deployment-d55b94fd-dj4lx 1/1 Running 0 2m15s
nginx-deployment-d55b94fd-g278x 1/1 Running 0 2m15s
nginx-deployment-d55b94fd-kp4v6 1/1 Running 0 2m15s
nginx-deployment-d55b94fd-pvq87 1/1 Running 0 2m15s
nginx-deployment-d55b94fd-rnnjz 1/1 Running 0 9s

כאשר ניתן לראות שהPOD האחרון נוצר לפני 9 שניות על מנת להחליף את הPOD שמחקתי, לעומת האחרים שנוצרו לפני 2 דקות.

אסטרטגיות Cache בשימוש ב ElastiCache

ElasticCache הוא שירות מנוהל של MemCached או Redis (ניתן לבחור איזה מהמנועים אנו מעוניינים להריץ) ומיועד לשפר את ביצועי מסד הנתונים שלנו על ידי שמירת שאילתות בCache.


הייתרונות בשירות מנוהל ברורים – חוסך לנו את הזמן הדרוש להתעסק בתחזוקה ובניהול השירות , ובעיקר את המומחיות הדרושה שלא תמיד זמינה לנו, ומאפשר לנו להיות מפוקסים בפיתוח המוצר שלנו.

אסטרטגיות פופולאריות:
Lazy Loading:
בשיטה זו אנו בעצם כותבים לCache כאשר ניסינו לקבל מידע ממנו והוא לא קיים.
הייתרון בשיטה זו הוא שאנו טוענים רק מידע שבעצם יש לנו צורך בו.
בדרך כלל אנו נשתמש בשיטה זו בצירוף שיטות אחרות.

Write Through

בשיטה זו, בכל פעם שאנו מבצעים כתיבה למסד הנתונים שלנו אנו מעדכנים את הCache בהתאם.
הייתרון בשיטה זו שהקאש תמיד מעודכן במידע האחרון
החיסרון העיקרי שאנו בעצם מגדילים את הזמן הדרוש לאפלקציה שלנו לבצע את העדכון במסד הנתונים כיון שבשיטה זו בנוסף לעדכון מסד הנתונים אנו מעדכנים גם את הקאש.
– שימו לב, בשיטה זו חשוב מאוד לקבוע TTL לקאש שלנו – אחרת הקאש שלנו יהיה מלא בדאטא שייתכן שאנו לא צריכים אותו.

TTL – Time To Live
מאפשר לנו להקטין את החסרונות הקיימים באסטרטגיות Write Through ו Lazy Loading
TTL זה הזמן שאנו מעוניינים שהמפתח Cache שלנו יהיה קיים – או יותר נכון, מתי אנו מעוניינים שהוא יימחק.
חשוב לזכור שTTL לכשעצמו לא מבטיח לנו שהמידע שיש לנו בקאש יהיה העדכני ביותר, הוא רק מבטיח לנו שהקאש שלנו לא יהיה במלא במידע שאנו לא צריכים אותו.
TTL בשיתוף עם Lazy Loading בעצם יאפשר לנו לאכול את העוגה ולהשאיר אותה שלמה – אנו גם כותבים לקאש רק מידע שאנו צריכים וגם שומרים אותו עדכני על ידי שימוש בTTL – החיסרון הוא שבפעם הראשונה שאנו נצטרך את הדאטא – אנו בעצם לא נהנים מהייתרונות של הCache.

הגדרה וקונפיגורציה של CodeDeploy

שימו לב! המאמר עדיין לא גמור ורק חלק מהשלבים הרלוונטים מפורטים ומוסברים בו.

  1. אנו צריכים ליצור משתמש IAM (משתמש Non-admin) עם פוליסת CodeDeploy על מנת לאפשר לו לנהל את כל מה שקשור לCodeDeploy. לחילופין אנו יכולים לשדך את הפוליסה ל"קבוצה" ולשייך את המשתמש שיצרנו לאותה קבוצה.
  2. יצירת Instance Profile – מאפשר לנו לתת גישה לקוד רפוסיטי שלנו לEC2.
  3. יצירת Service Role – יאפשר לCodeDeploy להתקשר עם שירותים נוספים של AWS
  4. התקנת AWS CLI (מומלץ)

בשלב הראשון ניצור משתמש IAM חדש בשם MyCodeDeployUser

על מנת ליצור פוליסה מתאימה, נלחץ על AMI ואז של Policies.שם נלחץ על Create Policy

ואז נבחר באופציה CodeDeploy ונבחר את הפוליסה בשם "AWSCodeDeployFullAccess" או פוליסה אחרת שמתאימה לנו בהתאם לצורך.

לאחר מכן אנו צריכים להצמיד את הפוליסה למשתמש שאנו מעוניינים שיהיו לו את כל ההרשאות הקשורות לניהול CodeDeploy. נעשה זאת על ידי בחירת המשתמש MyCodeDeployUser תחת משתמשי הIAM שלנו ואז נלחץ על הוספת הרשאות. (בתמונה שם הפוליסה הוא MyCodeDeployPolicy אבל אצלכם שם הפוליסה יהיה AwsCodeDeployFullAccess

הגדרת Service Role מתאים לEC2

ניגש לIAM ואז לRoles, ואז נלחץ על Create Role.
ברשימת השירותים נבחר את השירות CodeDeploy וב Use Case נבחר "CodeDeploy"


ניתן שם לRole ונקרא לו CodeDeployServiceRole

מה זה CodeDeploy

CodeDeploy הוא שירות של AWS שמאפשר לנו להפוך את תהליך הDeployment שלנו לאוטומטי.

ייתרונות:
* Scale – ניתן לעשות דפלוי לשרת אחד או לאלפי שרתים ביחד
* שליטה – מאפשר לנו לקבל עדכונים ודוחות עם מידע לגבי מתי ומה דפלויד למערכת.
* צימצום זמן הDown Time שלנו – מאפשר שיטות דפלוי שונות כמו Rolling Updates ועוד.
* ניתן לעשות שימוש בCodeDeploy בכל שפה או טכנולוגיה – בתנאי שהקוד מנוהל במנוע מסוג GIT כמו CodeCommit לדוגמה או שהקוד שלנו יושב בS3
* ניתן לעשות דפלוי לשרתי EC2, לקונטיינרים או לSERVERLESS

למה אנחנו יכולים לעשות דפלוי?
* כמובן לקוד שלנו
* פונקציות Lambada
* סקריפטים
* קבצי מולטימדיה
ועוד…

התקנת DOCKER בJenkins

על מנת שJENKINS יוכל לעשות דפלוי לאפלקציות בקונטיינרים (Containerized app), אנו צריכים להתקין את DOCKER על השרת שעליו רץ הג'נקינס שלנו.

בשלב הראשון נתקין את DOCKER ונפעיל את השירות

sudo yum -y install docker
sudo systemctl start docker
sudo systemctl enable docker

לאחר מכן ניתן הרשאות לג'נקינס להשתמש בDOCKER , כדי לעשות זאת ניצור קבוצה לDOCKER ונוסיף את המשתמש של ג'נקינס לקבוצה.

sudo groupadd docker
sudo usermod -aG docker jenkins

נפעיל מחדש את השירות JENKINS ואת DOCKER

sudo systemctl restart jenkins
sudo systemctl restart docker

זהו, ככה פשוט.


לקריאה נוספת:
1. איך להתקין Jenkins בCentOS7
2. יצירת Jenkins Job פשוט שמושך קבצים מGIT
3. על Jenkins וWebHooks – עדכון אוטומטי כאשר מתבצע שינוי בקוד בריפו שלנו
4. קצת על Jenkins Pipelines
5. התקנת DOCKER בJenkins

קצת על Jenkins Pipelines

Jenkins Piplines הם שילוב של פלאגינים של ג'נקינס שעוזרים לנו לממש Continuous Delivery בג'נקינס.

Pipline הוא תהליך אוטומטי שלוקח את קוד המקור שלנו דרך ה"Pipline" – עד לפרודקשין. בדרכ נממש בו לפחות 3 שלבים (STAGES),
Build, Test , Deploy.

קובץ הpipline נקרא Jenkinsfile ואנו שומרים אותו במערכת הSource Control שלנו ביחד עם קוד האפלקציה שלנו.

כדי ליצור Pipline חדש, כל שאנו צריכים לעשות הוא ליצור קובץ Jenkinsfile ולהוסיף אותו לGIT ריפו שלנו, לאחר מכן כשאנו יוצרים פרויקט ג'נקינס חדש – נבחר הפעם פרויקט מסוג Pipline או Multibranch Pipline.

דוגמה לpipline מסוג Declarative שלא עושה כלום מלבד ECHO של 3 השלבים (Stages):

pipeline {
    agent any 
    stages {
        stage('Build') { 
            steps {
                echo 'Building...' 
            }
        }
        stage('Test') { 
            steps {
                echo 'Testing...' 
            }
        }
        stage('Deploy') { 
            steps {
                echo 'Deploying!' 
            }
        }
    }
}

כל שלב או תהליך (STAGE) מכיל בתוכו "צעדים" (STEPS), לדוגמה צעד ראשון: להריץ פקודה מסויימת, צעד שני: להעתיק את הקבצים לשרת, צעד שלישי: לאתחל את APACHE.

לקריאה נוספת:
1. איך להתקין Jenkins בCentOS7
2. יצירת Jenkins Job פשוט שמושך קבצים מGIT
3. על Jenkins וWebHooks – עדכון אוטומטי כאשר מתבצע שינוי בקוד בריפו שלנו
4. קצת על Jenkins Pipelines
5. התקנת DOCKER בJenkins

מה זה Gradle Build?

Gradle Build מוגדר בקובץ בשם build.gradle (בשפת גרובי או קוטלין) שממוקם בתיקיית הROOT של הפרויקט.
על ידי הפקודה:

gradle init

אנו נוכל לאתחל פרויקט חדש ולהגדיר את הgradle wrapper. אגב, במידה ונריץ את הפקודה בפרויקט קיים, gradle ינסה לזהות את שפת הפרויקט וליצור קונפיגורציות מתאימות עבורנו בצורה אוטומטית.

כל gradle build מוגדר בעצם מ"משימות" – gradle tasks. כדי להריץ "משימה" ספציפית נריץ את הקוד הבא (בהנחה ושם המשימה שלנו הוא "sampletask1"

./gradlew sampletask1

קובץ הbuild.gradle שלנו בעצם אמור להכיל את כל המשימות שזמינות לפרויקט שלנו.

בדוגמה הבאה למשל ניצור "משימה" שקוראים לה "sampletask1" שכל מה שהיא עושה זה להדפיס את המילה "ישראל"

task sampletask1 {
  println 'Israel'
}

ניתן בנוסף להגדיר משימות שתלויות – Dependencies – במשימות אחרות, לדוגמה נוכל להגדיר 2 משימות, האחת בשם task1 והשנייה בשם task2 כאשר task2 תלויה במשימה task1, דהיינו המשימה task1 תהיה חייבת לרוץ ולהצליח לפני המשימה task2.

בנוסף לGradle יש המון תוספים – plugins שיכולים לעזור לנו בהמון מצבים, את התוספים אפשר לכלול בקובץ build.gradle שלנו , לדוגמה על ידי השורות הבאות

plugins {
 id "<plugin id here>" version "<plugin version here">
}

קובץ build לדוגמה:


/*
 * This file was generated by the Gradle 'init' task.
 *
 * This is a general purpose Gradle build.
 * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds
 */

task sayIsrael << {
 println 'Israel'
}

task task2 {
 println 'task task2 is here'
}

הקובץ מכיל 2 משימות, האחת בשם sayIsrael שמדפיסה Israel ומשימה שנייה בשם task2 שמדפיסה 'task task2 is here'

אם נריץ את הפקודה:

./gradlew sayIsrael

נקבל

[aviv@localhost test1]$ ./gradlew sayIsrael

> Configure project :
Israel
task task2 is here

BUILD SUCCESSFUL in 1s

וכשנריץ

./gradlew task2

נקבל:

[aviv@localhost test1]$ ./gradlew task2

> Configure project :
Israel
task task2 is here

BUILD SUCCESSFUL in 1s

כשנוסיף לקובץ בילד שלנו לדוגמה את השורה
sayIsrael.dependsOn task2
ונריץ שוב את המשימה sayIsrael נקבל הפעם

[aviv@localhost test1]$ ./gradlew -q sayIsrael
Israel
task task2 is here

למרות שהרצנו לכאורה רק את המשימה sayIsrael.

מצאתם טעות? הערות? שאלות? הסתדרתם? נתקעתם? כתבו לי בתגובות!

להמשיך לקרוא מה זה Gradle Build?

איך להתקין Gradle בCentos7

נריץ את הפקודות הבאות:

cd ~/
wget -O ~/gradle-bin.zip https://services.gradle.org/distributions/gradle-6.0.1-bin.zip
sudo yum -y install unzip java-1.8.0-openjdk
sudo mkdir /opt/gradle
sudo unzip -d /opt/gradle/ ~/gradle-bin.zip

נערוך את הקובץ gradle.sh על ידי הפקודה הבאה:

sudo nano /etc/profile.d/gradle.sh

ונכתוב לקובץ את השורה הבאה:

export PATH=$PATH:/opt/gradle/gradle-6.0.1/bin

ניתן הרשאות מתאימות לקובץ gradle.sh

sudo chmod 755 /etc/profile.d/gradle.sh

אחרי שעשינו Logout וLogin מחדש למכונה, נריץ את הפקודה הבאה כדי לוודא שההתקנה בוצעה בהצלחה

gradle --version

זהו, ככה קל.

[aviv@localhost ~]$ gradle --version

Welcome to Gradle 6.0.1!

Here are the highlights of this release:
 - Substantial improvements in dependency management, including
   - Publishing Gradle Module Metadata in addition to pom.xml
   - Advanced control of transitive versions
   - Support for optional features and dependencies
   - Rules to tweak published metadata
 - Support for Java 13
 - Faster incremental Java and Groovy compilation
 - New Zinc compiler for Scala
 - VS2019 support
 - Support for Gradle Enterprise plugin 3.0

For more details see https://docs.gradle.org/6.0.1/release-notes.html


------------------------------------------------------------
Gradle 6.0.1
------------------------------------------------------------

Build time:   2019-11-18 20:25:01 UTC
Revision:     fad121066a68c4701acd362daf4287a7c309a0f5

Kotlin:       1.3.50
Groovy:       2.5.8
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          1.8.0_232 (Oracle Corporation 25.232-b09)
OS:           Linux 3.10.0-1062.9.1.el7.x86_64 amd64

כדי להתקין את Graddle Wrapper נריץ את הפקודות הבאות:

cd ~/
mkdir my-project
cd my-project
gradle wrapper
./gradlew build

לאתר Gradle
https://gradle.org/


מצאתם טעות? הערות? שאלות? הסתדרתם? נתקעתם? כתבו לי בתגובות!

להמשיך לקרוא איך להתקין Gradle בCentos7

Networking בקוברנטיס – איך Pods מדברים בניהם – מבט בסיסי

לקריאה מקדימה:
* קצת על קוברנטיס
* מה זה Node וקלסטרינג בקוברנטיס
* מה זה POD?
* איך ליצור קוברנטיס קלסטר בסיסי בקלות?


קוברנטיס מאפשר לנו ליצור Virtual Network שפועל בכל הקלסטר שלנו, כל Pod בקלסטר מקבל כתובת IP ייחודית ויכול לתקשר עם כל pod אחר בקלסטר – גם במיקרה שהPod רץ בNode אחר.

קוברנטיס תומך במספר רב של תוספים (Plugins) של networking, ברוב ההדגמות בבלוג, אני עושה שימוש בתוסף שקוראים לו Flannel – כדי להתקין אותו עקבו אחר ההוראות שמופיעות כאן.

הקובץ Yaml הבא יוצר לדוגמה 3 Pods (להלן 3 רפליקות), כאשר כל POD יריץ קונטיינר (Docker) של Nginx

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4
        ports:
        - containerPort: 80

אנו ניצור POD נוסף שיריץ busybox , באמצעותו נוכל לבדוק את הקישוריות שלנו בין הPODS השונים (נשתמש בCURL).

apiVersion: v1
kind: Pod
metadata:
  name: avivbusybox
spec:
  containers:
  - name: avivbusybox
    image: radial/busyboxplus:curl
    args:
    - sleep
    - "2000"

לאחר מכן נריץ את הפקודה הבאה כדי לקבל רשימה של הPODS שלנו כולל כתובת הIP שלהם:

kubectl get pods -o wide

בשלב האחרון ננסה להריץ CURL מתוך הbusybox שלנו לכתובת הIP של הפודים האחרים שלנו, כאשר את ה00.00.00.00 אנו נחליף בכתובת הIP של הפוד אליו אתה רוצים לבצע את הCURL.
הפקודה kubectl exec busybox בעצם מריצה את הcurl 00.00.00.00 בתוך POD הbusybox שלנו.

kubectl exec busybox -- curl 00.00.00.00

במידה והצלחנו לבצע CURL וקיבלנו את עמוד הדיפולט של Nginx זה בעצם מוכיח, שPODS יכולים לתקשר בניהם, גם אם הם ממוקמים בNodes אחר ושההתקנה של Flannel בוצעה בהצלחה.

לקריאה נוספת:
* הגדרות רשת עם Flannel
* https://kubernetes.io/docs/concepts/cluster-administration/networking/
* https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/
* https://github.com/coreos/flannel


מצאתם טעות? הערות? שאלות? הסתדרתם? נתקעתם? כתבו לי בתגובות!