Monday, July 13, 2020

AWS CODECOMMIT WITH ANSIBLE-(JUST FOR FUN AND PRACTICE.)

 Howdy?

 This article is only for practicing ansible and aws codecommit.
You might think this is automation drill?.

 In a real situation, codecommit repository will be created with our mouse's click and click, and ssh key and git credential by manually cause necessary codecommit repositories are very limited in most cases.

 Nonetheless, parts of this playbook yaml, such as "creating ssh keys" and "and applying that in local env" could be useful for our automation life.

 1. We should prepare aws-cli and ansible(python3) installation.

*aws cli)
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html

*ansible)
oyj@controller:~$ pip3 install virtualenv --user

oyj@controller:~$ virtualenv anbawscmmit
created virtual environment CPython3.6.9.final.0-64 in 391ms
  creator CPython3Posix(dest=/home/oyj/deploy_aws/anbawscmmit, clear=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/oyj/.local/share/virtualenv)
    added seed packages: pip==20.1.1, setuptools==47.2.0, wheel==0.34.2
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
oyj@controller:~$ source anbawscmmit/bin/activate

oyj@controller:~$ source anbawscmmit/bin/activate
(anbawscmmit) oyj@controller:~$

(anbawscmmit) oyj@controller:~$ pip3 install ansible
Collecting ansible
  Downloading ansible-2.9.10.tar.gz (14.2 MB)
     |████████████████████████████████| 14.2 MB 306 kB/s
Collecting jinja2
  Using cached Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting PyYAML
....


(anbawscmmit) oyj@controller:~$ ansible --version
ansible 2.9.10
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/oyj/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/oyj/anbawscmmit/lib/python3.6/site-packages/ansible
  executable location = /home/oyj/anbawscmmit/bin/ansible
  python version = 3.6.9 (default, Apr 18 2020, 01:56:04) [GCC 8.4.0]



(anbawscmmit) oyj@controller:~/ansible-aws$ pip3 install boto3
Collecting boto3

#Until now it is ok.

2. Clone github repo , create aws codecommit repository and upload below node sources.

(anbawscmmit) oyj@controller:~/ansible-aws$ ls node_auth
app.js  appspec.yml  core  package.json  package-lock.json  public  routes  scripts  views

(anbawscmmit) oyj@controller:~$ git clone https://github.com/ohyoungjooung2/ansible-aws.git

Receiving objects: 100% (163/163), 13.87 MiB | 6.14 MiB/s, done.
Resolving deltas: 100% (74/74), done.


(anbawscmmit) oyj@controller:~$ cd ansible-aws/
#ansible playbook. All playbook codes are commented.

#As you see below, codecommit user is "cc_user",  ssh_key_name : "codecommit_key"..and so on.

(anbawscmmit) oyj@controller:~/ansible-aws$ cat create_user_cmmitrepo_upload_nodeauth_app.yaml | head -20
---
- hosts: localhost
  connection: local
  gather_facts: no

  vars:
    #Codecommit user
    user1: 'cc_user'
    REGION: 'ap-northeast-2'
    SSH_KEY_NAME: 'codecommit_key'
    LOCAL_HOME: "{{ lookup('env','HOME')}}"
    REPO_NAME: 'node_auth'
    SSH_GIT_URL: 'ssh://git-codecommit.{{ REGION }}.amazonaws.com/v1/repos/{{ REPO_NAME }}'
    #STATE: 'absent'
    STATE: 'present'

.......rest codes..



(anbawscmmit) oyj@controller:~/ansible-aws$ ansible-playbook create_user_cmmitrepo_upload_nodeauth_app.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ***********************************************************************************************************

TASK [Detach codecommit full permission to codecommit_user] ****************************************************************
skipping: [localhost] => (item=cc_user)

TASK [Delete cc_user] ******************************************************************************************************
skipping: [localhost] => (item=cc_user)

RUNNING HANDLER [git source commmit and upload to codecommit] **************************************************************
changed: [localhost]

PLAY RECAP *****************************************************************************************************************
localhost                  : ok=12   changed=8    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0  
#OK!
(anbawscmmit) oyj@controller:~/ansible-aws$

#codecommit user cc_user created with ssh pub key.



#Below repository created.





 #The ssh config for codecommit repo created.
 (anbawscmmit) oyj@controller:~/ansible-aws$ cat ~/.ssh/config
Host git-codecommit.*.amazonaws.com
User APKAXGFYD7MIQPBPIHOG
IdentityFile /home/oyj/ansible-aws/codecommit_key



 #Test
 (anbawscmmit) oyj@controller:~/ansible-aws$ aws codecommit get-repository --repository-name node_auth
{
         "cloneUrlSsh": "ssh://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/node_auth",
        "Arn": "arn:aws:codecommit:ap-northeast-2:494307375889:node_auth"
    }
}
(anbawscmmit) oyj@controller:/tmp/testcmmit$ git clone https://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/node_auth
Cloning into 'node_auth'...
Username for 'https://git-codecommit.ap-northeast-2.amazonaws.com': ^C
(anbawscmmit) oyj@controller:/tmp/testcmmit$ git clone ssh://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/node_auth
Cloning into 'node_auth'...
remote: Counting objects: 31, done.
Receiving objects: 100% (31/31), 53.04 KiB | 6.63 MiB/s, done.
Resolving deltas: 100% (2/2), done.


#push test
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ touch testfile.txt
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ echo "test add file" > testfile.txt
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ git add testfile.txt
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ git commit -m "testing add file to cmmit"
[master 6c43b5e] testing add file to cmmit
 1 file changed, 1 insertion(+)
 create mode 100644 testfile.txt
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 285 bytes | 285.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To ssh://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/node_auth
   81ad1a2..6c43b5e  master -> master



#Test with another user.
A)Copy .ssh/config to another user's .ssh/config and change key location.

(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ sudo cp ~/.ssh/config /home/testcmit/.ssh/ -f

(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ sudo cp ~/ansible-aws/codecommit_key /home/testcmit/
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ sudo chown -R testcmit.testcmit /home/testcmit/
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$
#su -
(anbawscmmit) oyj@controller:/tmp/testcmmit/node_auth$ sudo su - testcmit
testcmit@controller:~$ vi ~/.ssh/config
Host git-codecommit.*.amazonaws.com
User APKAXGFYD7MIQPBPIHOG
IdentityFile /home/testcmit/codecommit_key


#Clone this repo!
testcmit@controller:~$ git clone ssh://git-codecommit.ap-northeast-2.amazonaws.com/v1/repos/node_auth

testcmit@controller:~/node_auth$ ls
app.js  appspec.yml  core  package.json  package-lock.json  public  routes  scripts  testfile.txt  views
testcmit@controller:~/node_auth$ cat testfile.txt
test add file


#Well it works!(Apache!)

#Lastly I will delete this codecommit repo with ansible(same playbook but different options)

#With "-e "STATE=absent"" option. We could all codecommit related things all at once.

(anbawscmmit) oyj@controller:~/ansible-aws$ ansible-playbook create_user_cmmitrepo_upload_nodeauth_app.yaml -e "STATE=absent"

TASK [Delete cc_user] ******************************************************************************************************
changed: [localhost] => (item=cc_user)

RUNNING HANDLER [git source commmit and upload to codecommit] **************************************************************
skipping: [localhost]

PLAY RECAP *****************************************************************************************************************
localhost                  : ok=10   changed=5    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0 


Conclusion)
 With ansilbe, aws configuration could be very convenient and automatic with just one line command but lots of configuration and file works.

Thanks for reading!












Sunday, July 12, 2020

DEPLOYMENT SPRINGBOOT-API-MYSQL APP ON LOCAL K8S CLUSTER USING AWS ECR.


 This article shows how to deploy java spboot-api-mysql application into local k8s(1.17) cluster. I have not enough resource on my desktop, so I use AWS ecr as a docker registory. This could be used as a hybrid cloud context. As a storage, I use nfs server that is only used in development or experimental environment.

Currently, I have this local k8s clusters.(Using vagrant and libvirt).
All command line is on Linux box(I use xubuntu).
And aws-cli is already configured on my box and cluster(k8s master)


#Cluster one master and 2 worker nodes.
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get no
NAME          STATUS   ROLES    AGE     VERSION
kubemaster    Ready    master   6d20h   v1.17.0
kubeworker1   Ready    <none>   6d20h   v1.17.0
kubeworker2   Ready    <none>   6d20h   v1.17.0


#Vagrant
oyj@controller:~/prac/u18kvk8s/k8s$ vagrant status
Current machine states:

kubemaster                running (libvirt)
kubeworker1               running (libvirt)
kubeworker2               running (libvirt)
nfserver                  running (libvirt)

1. Create spboot-api-mysl docker image.
 #git clone
oyj@controller:~/prac$ git clone https://github.com/ohyoungjooung2/spboot-api-mysl.git

 #Mysql database authorization. Currently I installed mysql on my desktop .

root@controller:~# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30-0ubuntu0.18.04.1 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database spbootapimysl
    -> ;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON spbootapimysl.* TO 'spboot'@'%' IDENTIFIED BY '!GoodPassplz#8';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

oyj@controller:~/prac/spboot-api-mysl$ mysql -u spboot -p spbootapimysl
Enter password:


mysql> show tables;
Empty set (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| spbootapimysl      |
+--------------------+
2 rows in set (0.00 sec)

#Modify application.properties file.

oyj@controller:~/prac/spboot-api-mysl$ vi src/main/resources/application.properties


server.port=10001
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url = jdbc:mysql://localhost:3306/spbootapimysl?characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.url = jdbc:mysql://172.17.0.1:3306/spbootapimysl?characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username = spboot
spring.datasource.password = !GoodPassplz#8
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
logging.level.web=debug


#Create jar
oyj@controller:~/prac/spboot-api-mysl$ ./mvnw install

[INFO] Installing /home/oyj/prac/spboot-api-mysl/target/spriboot-crud-api-mysql-0.0.1-SNAPSHOT.jar to /home/oyj/.m2/repository/com/myqlapi/spriboot-crud-api-mysql/0.0.1-SNAPSHOT/spriboot-crud-api-mysql-0.0.1-SNAPSHOT.jar
[INFO] Installing /home/oyj/prac/spboot-api-mysl/pom.xml to /home/oyj/.m2/repository/com/myqlapi/spriboot-crud-api-mysql/0.0.1-SNAPSHOT/spriboot-crud-api-mysql-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.499 s
[INFO] Finished at: 2020-07-13T00:17:56+09:00
[INFO] ------------------------------------------------------------------------

oyj@controller:~/prac/spboot-api-mysl$ ls target/spriboot-crud-api-mysql-0.0.1-SNAPSHOT.jar
target/spriboot-crud-api-mysql-0.0.1-SNAPSHOT.jar



#Docker build
oyj@controller:~/prac/spboot-api-mysl$ cat Dockerfile
FROM openjdk:8-jdk-alpine AS builder
WORKDIR target/dependency
ARG APPJAR=target/*.jar
COPY ${APPJAR} app.jar
RUN jar -xf ./app.jar


FROM openjdk:8-jre-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY --from=builder ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=builder ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.myqlapi.crudapi.ex.SpribootCrudApiMysqlApplication"]


oyj@controller:~/prac/spboot-api-mysl$ docker build . -t spboot-api-mysl:latest


Step 8/12 : ARG DEPENDENCY=target/dependency
 ---> Using cache
 ---> f4adeb4a8754
Step 9/12 : COPY --from=builder ${DEPENDENCY}/BOOT-INF/lib /app/lib
 ---> Using cache
 ---> 5d08fda48513
Step 10/12 : COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF
 ---> Using cache
 ---> f0b5e97bbd7b
Step 11/12 : COPY --from=builder ${DEPENDENCY}/BOOT-INF/classes /app
 ---> Using cache
 ---> aa8f20b7e63e
Step 12/12 : ENTRYPOINT ["java","-cp","app:app/lib/*","com.myqlapi.crudapi.ex.SpribootCrudApiMysqlApplication"]
 ---> Using cache
 ---> 4f2a73bf2e33
Successfully built 4f2a73bf2e33
Successfully tagged spboot-api-mysl:latest

#Run docker
docker run -d -p 127.0.0.1:10000:10001 spboot-api-mysl


#Check with curl.
oyj@controller:~/prac/spboot-api-mysl$ curl http://localhost:10000/products
[]
oyj@controller:~/prac/spboot-api-mysl$
#Post and delete check.

oyj@controller:~/prac/spboot-api-mysl$ curl -H "Content-Type: applicati{ "name":"AppleCar","quantity":3,"price":20000}' http://localhost:10000/addproduct/
{"id":1,"name":"AppleCar","quantity":3,"price":20000.0}oyj@controller:~/prac/spboot-api-mysl$

oyj@controller:~/prac/spboot-api-mysl$ curl http://localhost:10000/products
[{"id":1,"name":"AppleCar","quantity":3,"price":20000.0}]oyj@controller:~/prac/spboot-api-mysl$


oyj@controller:~/prac/spboot-api-mysl$ curl -H "Content-Type:application/json" -X DELETE http://localhost:10000/delete/1
product removed!!1oyj@controller:~/prac/spboot-api-mysl$
oyj@controller:~/prac/spboot-api-mysl$ curl http://localhost:10000/products
[]oyj@controller:~/prac/spboot-api-mysl$


#It works well.^^

2. Upload image into AWS ECR.

#Create repository
oyj@controller:~/prac/spboot-api-mysl$ aws ecr create-repository --repository-name spboot-api-mysl --image-tag-mutability IMMUTABLE
{
    "repository": {
        "repositoryArn": "arn:aws:ecr:ap-northeast-2:494307375889:repository/spboot-api-mysl",
        "registryId": "494307375889",
        "repositoryName": "spboot-api-mysl",
        "repositoryUri": "494307375889.dkr.ecr.ap-northeast-2.amazonaws.com/spboot-api-mysl",
        "createdAt": "2020-07-13T01:01:31+09:00",
        "imageTagMutability": "IMMUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        }
    }
}

#Tag and push
oyj@controller:~/prac/spboot-api-mysl$ docker tag spboot-api-mysl:latest 494307375889.dkr.ecr.ap-northeast-2.amazonaws.com/spboot-api-mysl:latest

oyj@controller:~/prac/spboot-api-mysl$ docker push  494307375889.dkr.ecr.ap-northeast-2.amazonaws.com/spboot-api-mysl:latest
The push refers to repository [494307375889.dkr.ecr.ap-northeast-2.amazonaws.com/spboot-api-mysl]
23e0111c8ffa: Pushed
5c43cd603e6d: Pushed
c20cb2b5afc9: Pushed
edd61588d126: Pushed
9b9b7f3d56a0: Pushed
f1b5933fe4b5: Pushed
latest: digest: sha256:29a19a56a09bae22a1b83b20d869d8b217fc1eb4f390192c7b97a6ee9e10a702 size: 1575

#Image List
oyj@controller:~/prac/spboot-api-mysl$ aws ecr list-images --repository-name spboot-api-mysl
{
    "imageIds": [
        {
            "imageDigest": "sha256:29a19a56a09bae22a1b83b20d869d8b217fc1eb4f390192c7b97a6ee9e10a702",
            "imageTag": "latest"
        }
    ]
}


3. Create mysql service and api,mysql pod deployment on local k8s cluster.
   ref) How to create nfs provisioner.
  
  1) nfs storage : create storage class.
    [vagrant@kubemaster sprngbootmysqlapi]$ vi stclassForApi.yaml
[vagrant@kubemaster sprngbootmysqlapi]$ cat stclassForApi.yaml
#For k8s 1.17
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: api-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false" # When set
        
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl create -f stclassForApi.yaml
storageclass.storage.k8s.io/api-nfs-storage created
[vagrant@kubemaster sprngbootmysqlapi]$

[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get sc api-nfs-storage
NAME              PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
api-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  52s

  2) Claim storage.

[vagrant@kubemaster sprngbootmysqlapi]$ cat stclaimForMysl.yaml
#For 1.17 for now(18?)
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: st-claim-for-api-mysql
  annotations:
    volume.beta.kubernetes.io/storage-class: "api-nfs-storage"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

#For mysql server
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl create -f stclaimForMysl.yaml
persistentvolumeclaim/st-claim-for-api-mysql created
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get pvc | grep api
st-claim-for-api-mysql     Bound    pvc-59ccf3a8-fe96-4e99-922b-4b091e04d596   2Gi        RWX            api-nfs-storage       8s

#For api app
[vagrant@kubemaster sprngbootmysqlapi]$ vi stclaimForapp.yaml
[vagrant@kubemaster sprngbootmysqlapi]$ cat stclaimForapp.yaml
#For 1.17 for now(18?)
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: st-claim-for-api-app
  annotations:
    volume.beta.kubernetes.io/storage-class: "api-nfs-storage"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

[vagrant@kubemaster sprngbootmysqlapi]$ kubectl create -f stclaimForapp.yaml
persistentvolumeclaim/st-claim-for-api-app created
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get pvc st-claim-for-api-app
NAME                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
st-claim-for-api-app   Bound    pvc-bb6afcc0-adf5-424b-816b-a9014b67ad76   1Gi        RWX            api-nfs-storage   10s




  3) kustomization.yaml creation.
[vagrant@kubemaster sprngbootmysqlapi]$ cat kustomization.yaml

secretGenerator:
- name: mysql-root-pass
  literals:
  - password=StrongPass$^^$
- name: spriapi-database
  literals:
  - database=spbootapimysl
  - url='jdbc:mysql://spboot-api-mysl-host:3306/spbootapimysl?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false'
- name: mysql-user-pass
  literals:
  - username=spriboot
  - password=!passGood$8

resources:
  - spboot-api-mysl-dp.yaml
  - api-mysl-srv-dp.yaml



 4) Create api-mysl-srv-dp.yaml (deployment) and spboot-api-mysl-dp.yaml
  [vagrant@kubemaster sprngbootmysqlapi]$ cat api-mysl-srv-dp.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: spboot-api-mysl-srv
  labels:
    app: spboot-api-mysl-srv
spec:
  selector:
    matchLabels:
      app: spboot-api-mysl-srv
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: spboot-api-mysl-srv
        tier: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-root-pass
              key: password
        - name: MYSQL_DATABASE
          valueFrom:
            secretKeyRef:
              name: spriapi-database
              key: database
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-user-pass
              key: username
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-user-pass
              key: password

        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: st-claim-for-api-mysql



[vagrant@kubemaster sprngbootmysqlapi]$ cat spboot-api-mysl-dp.yaml
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: spboot-api-mysl
  labels:
    app: spboot-api-mysl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spboot-api-mysl
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: spboot-api-mysl
    spec:
      containers:
      - image: 494307375889.dkr.ecr.ap-northeast-2.amazonaws.com/spboot-api-mysl:latest
        name: spboot-api-mysl
        env:
        - name: SPRING_DATASOURCE_USERNAME
          valueFrom:
            secretKeyRef:
              name: mysql-user-pass
              key: username
           
        - name: SPRING_DATASOURCE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-user-pass
              key: password
        - name: SPRING_DATASOURCE_URL
          valueFrom:
            secretKeyRef:
              name: spriapi-database
              key: url
        ports:
        - containerPort: 10001
          name: spboot-api-mysl

        volumeMounts:
        - name: spboot-api-mysl-persistent-storage
          mountPath: /tmp
      #this is generate with bash shell below. 5)
      imagePullSecrets:
       - name: ap-northeast-2-ecr-registry

      volumes:
      - name: spboot-api-mysl-persistent-storage
        persistentVolumeClaim:
          claimName: st-claim-for-api-app



 5)Get authrized to retrive ecr docker image.
   [vagrant@kubemaster sprngbootmysqlapi]$ vi get_aws_token_ecr.sh
[vagrant@kubemaster sprngbootmysqlapi]$ cat get_aws_token_ecr.sh
#!/usr/bin/env bash
#This script is from stackexchange.com. Many thanks.
ACCOUNT=494307375889
REGION=ap-northeast-2
SECRET_NAME=${REGION}-ecr-registry
EMAIL=email@email.com

#
#

TOKEN=`aws ecr --region=$REGION get-authorization-token --output text \
    --query authorizationData[].authorizationToken | base64 -d | cut -d: -f2`

#
#  Create or replace registry secret
#


kubectl delete secret --ignore-not-found $SECRET_NAME
kubectl create secret docker-registry $SECRET_NAME \
    --docker-server=https://${ACCOUNT}.dkr.ecr.${REGION}.amazonaws.com \
    --docker-username=AWS \
    --docker-password="${TOKEN}" \
    --docker-email="${EMAIL}"
[vagrant@kubemaster sprngbootmysqlapi]$ bash get_aws_token_ecr.sh
secret "ap-northeast-2-ecr-registry" deleted
secret/ap-northeast-2-ecr-registry created

6) Create mysql service(svc).
[vagrant@kubemaster sprngbootmysqlapi]$ vi api-mysl-svc.yaml
[vagrant@kubemaster sprngbootmysqlapi]$ cat api-mysl-svc.yaml
#For 1.17
apiVersion: v1
kind: Service
metadata:
  name: spboot-api-mysl-host
  labels:
    app: spboot-api-mysl-srv
spec:
  ports:
    - port: 3306
  selector:
    app: spboot-api-mysl-srv
    tier: mysql
  clusterIP: None
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl create -f api-mysl-svc.yaml
service/spboot-api-mysl-host created
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get svc
NAME                           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes                     ClusterIP   10.96.0.1    <none>        443/TCP    6d23h
spboot-api-mysl-host           ClusterIP   None         <none>        3306/TCP   6s


7) Execute kustomization.yaml
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl apply -k .
secret/mysql-root-pass-82tbbm75f9 created
secret/mysql-user-pass-c2t6ghdcf5 created
secret/spriapi-database-9b2mktcc2h created
deployment.apps/spboot-api-mysl-srv created
deployment.apps/spboot-api-mysl configured
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get po
NAME                                      READY   STATUS              RESTARTS   AGE
nfs-client-provisioner-67b6b87bc9-fgmtr   1/1     Running             2          2d
nfs-client-provisioner-67b6b87bc9-tcw5r   1/1     Running             2          2d
spboot-api-mysl-865f787d56-q656t          0/1     ContainerCreating   0          2s
spboot-api-mysl-srv-858f7db96-v8qhq       1/1     Running             0          74s
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get po
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-67b6b87bc9-fgmtr   1/1     Running   2          2d
nfs-client-provisioner-67b6b87bc9-tcw5r   1/1     Running   2          2d
spboot-api-mysl-865f787d56-q656t          1/1     Running   0          5s
spboot-api-mysl-srv-858f7db96-v8qhq       1/1     Running   0          77s
[vagrant@kubemaster sprngbootmysqlapi]$




 8) #Test with curl.
   [vagrant@kubemaster sprngbootmysqlapi]$ curl http://10.244.1.35:10001/products
[]
[vagrant@kubemaster sprngbootmysqlapi]$ curl -H "Content-Type: application/json" -X POST -d '{"name":"ApplCar","quantity":3,"price":10000}' http://10.244.1.35:10001/addproduct/
{"id":1,"name":"ApplCar","quantity":3,"price":10000.0}[vagrant@kubemaster sprngbootmysqlapi]$
[vagrant@kubemaster sprngbootmysqlapi]$ curl http://10.244.1.35:10001/products
[{"id":1,"name":"ApplCar","quantity":3,"price":10000.0}][vagrant@kubemaster sprngbootmysqlapi]$
[vagrant@kubemaster sprngbootmysqlapi]$


 9) Create svc as node port.
[vagrant@kubemaster sprngbootmysqlapi]$ vi svc-spboot-api-mysql.yaml
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl create -f svc-spboot-api-mysql.yaml
service/spboot-api-mysl-svc created
[vagrant@kubemaster sprngbootmysqlapi]$ cat svc-spboot-api-mysql.yaml
apiVersion: v1
kind: Service
metadata:
  name: spboot-api-mysl-svc
  labels:
    app: spboot-api-mysl
spec:
  ports:
    - port: 10001
  selector:
    app: spboot-api-mysl
  type: NodePort
  ports:
  - port: 10001
    #3000~32767
    nodePort: 32222
    targetPort: 10001
    protocol: TCP
    name: http
[vagrant@kubemaster sprngbootmysqlapi]$ kubectl get svc spboot-api-mysl-svc
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE
spboot-api-mysl-svc   NodePort   10.107.183.192   <none>        10001:32222/TCP   34s


10) Node port test(my nodes are vagrant's each node ip: 10.1.0.3, 10.1.0.4)
   oyj@controller:~$ curl http://10.1.0.3:32222/products/
[{"id":1,"name":"ApplCar","quantity":3,"price":10000.0}]oyj@controller:~$
oyj@controller:~$ curl http://10.1.0.4:32222/products/
[{"id":1,"name":"ApplCar","quantity":3,"price":10000.0}]o




Conclusion)
Deployment api app(java) on k8s cluster using AWS ECR repo is kinda exceptional and fun. This cloud be very useful in development environment.
Besides, aws eks is somewhat expensive?, so local k8s cluster(not minikube) is good for testing I suppose.


Thanks for reading.



Tuesday, July 7, 2020

K8S-AWS-EKS-ECR-SPRING_BOOT-DEPLOYMENT-WITH-TERRAFORM-AND-BASH-SHELL

Howdy?

This blog post shows how to run eks on aws with terraform and bash shell. And also simple java web application deployment with kubectl.


  1.  Clone my git  repo that includes tf and shell files for provisioning eks. And terraform apply with shell
  2.  JAVA SPRING-BOOT DEPLOYMENT.
  3.  CONCLUSION

Saturday, December 28, 2019

K8s(kurbernetes 1.17) provisioning with vagrant and kvm(libvirt).

Prequisites).
In thie blog post, I will show how to provision k8s 1.17 with vagrant and some shell scripts.

Ubuntu18.04,vagrant and kvm environment.

*First of all, we should install vagrant and libvirt plugin.


oyj@controller:~$ vagrant plugin list
==> vagrant: A new version of Vagrant is available: 2.2.6 (installed version: 2.2.5)!
==> vagrant: To upgrade visit: https://www.vagrantup.com/downloads.html

vagrant-libvirt (0.0.45, global)

#If we did not install libvirt plugin, install like below.
oyj@controller:~$ vagrant plugin install libvirt
Installing the 'libvirt' plugin. This can take a few minutes...


*Second of all, we should clone git repo that I created recently.

oyj@controller:~$ git clone https://github.com/ohyoungjooung2/u18kvk8s.git
Cloning into 'u18kvk8s'...
remote: Enumerating objects: 216, done.
remote: Counting objects: 100% (216/216), done.
remote: Compressing objects: 100% (173/173), done.
remote: Total 216 (delta 36), reused 207 (delta 32), pack-reused 0
Receiving objects: 100% (216/216), 894.49 KiB | 942.00 KiB/s, done.
Resolving deltas: 100% (36/36), done.

*Lastly, just execute setup.sh.

oyj@controller:~$ cd u18kvk8s/k8s/
ooyj@controller:~/u18kvk8s/k8s$ bash setup.sh
Deleting previous id_rsa
 Generating ssh key for provisionng automatic
 copy id_rsa.put to pub_key
 up master first
Bringing machine 'kubemaster' up with 'libvirt' provider...
==> kubemaster: Checking if box 'centos/7' version '1905.1' is up to date...
==> kubemaster: Creating image (snapshot of base box volume).
==> kubemaster: Creating domain with the following settings...
==> kubemaster:  -- Name:              k8s_kubemaster
==> kubemaster:  -- Domain type:       kvm
==> kubemaster:  -- Cpus:              2
==> kubemaster:  -- Feature:           acpi
==> kubemaster:  -- Feature:           apic
==> kubemaster:  -- Feature:           pae
==> kubemaster:  -- Memory:            2048M
==> kubemaster:  -- Management MAC:   
==> kubemaster:  -- Loader:           
==> kubemaster:  -- Nvram:            
==> kubemaster:  -- Base box:          centos/7
==> kubemaster:  -- Storage pool:      default
==> kubemaster:  -- Image:             /var/lib/libvirt/images/k8s_kubemaster.img (41G)
==> kubemaster:  -- Volume Cache:      default
==> kubemaster:  -- Kernel:           
==> kubemaster:  -- Initrd:           
==> kubemaster:  -- Graphics Type:     vnc
==> kubemaster:  -- Graphics Port:     -1
==> kubemaster:  -- Graphics IP:       127.0.0.1
==> kubemaster:  -- Graphics Password: Not defined
==> kubemaster:  -- Video Type:        cirrus
==> kubemaster:  -- Video VRAM:        9216
==> kubemaster:  -- Sound Type:   
==> kubemaster:  -- Keymap:            en-us
==> kubemaster:  -- TPM Path:         
==> kubemaster:  -- INPUT:             type=mouse, bus=ps2
==> kubemaster: Creating shared folders metadata...
==> kubemaster: Starting domain.
==> kubemaster: Waiting for domain to get an IP address...
==> kubemaster: Waiting for SSH to become available...
    kubemaster:


===============omitted..too long ====================

Password authentication is disabled to avoid man-in-the-middle attacks.
Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks.
admin_init.log                                100% 4605     7.0MB/s   00:00   
scp admin_inig.log success
Wait until kubemaster ready to accept nodes to join

kubeworker2: Warning: Permanently added '10.1.0.2' (ECDSA) to the list of known hosts.
    kubeworker2:  Node will join with master 10.1.0.2
    kubeworker2: [preflight] Running pre-flight checks
    kubeworker2: W1228 11:31:10.356519    6787 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
    kubeworker2: [preflight] Reading configuration from the cluster...
    kubeworker2: [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
    kubeworker2: [kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.17" ConfigMap in the kube-system namespace
    kubeworker2: [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
    kubeworker2: [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
    kubeworker2: [kubelet-start] Starting the kubelet
    kubeworker2: [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
    kubeworker2:
    kubeworker2: This node has joined the cluster:
    kubeworker2: * Certificate signing request was sent to apiserver and a response was received.
    kubeworker2: * The Kubelet was informed of the new secure connection details.
    kubeworker2:
    kubeworker2: Run 'kubectl get nodes' on the control-plane to see this node join the cluster.



* And we can check by logging in kubemaster node.

oyj@controller:~/u18kvk8s/k8s$ vagrant ssh kubemaster
Last login: Sat Dec 28 11:20:50 2019
[vagrant@kubemaster ~]$ kubectl get nodes
NAME          STATUS   ROLES    AGE     VERSION
kubemaster    Ready    master   14m     v1.17.0
kubeworker1   Ready    <none>   5m34s   v1.17.0
kubeworker2   Ready    <none>   2m48s   v1.17.0



Conclusion).
To sum up, we can create k8s environment with vagrant and some shell scripts. Easy!..^^.

Thanks for reading.