{"id":63,"date":"2020-01-26T00:43:36","date_gmt":"2020-01-25T22:43:36","guid":{"rendered":"http:\/\/blog.nikster.de\/wordpress\/?p=63"},"modified":"2020-02-27T23:56:02","modified_gmt":"2020-02-27T21:56:02","slug":"how-to-set-up-a-devops-pipeline-with-gitlab-and-kubernetes","status":"publish","type":"post","link":"https:\/\/blog.nikster.de\/wordpress\/index.php\/2020\/01\/26\/how-to-set-up-a-devops-pipeline-with-gitlab-and-kubernetes\/","title":{"rendered":"How To set up a DevOps Pipeline with gitlab and kubernetes"},"content":{"rendered":"\n<h5 class=\"wp-block-heading\">What&#8217;s a pipeline?<\/h5>\n\n\n\n<p>In short: A Pipeline helps you to get your code (or in general: service) from Development (stage) to production (stage) in a short time, while providing the ability for automatic tests in a consistent environment.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">What&#8217;s this about?<\/h5>\n\n\n\n<p>I&#8221;ll build a pipeline that builds a web server in a docker container, tests it&#8217;s functionality and finally deploys it into a production environment. <\/p>\n\n\n\n<h5 class=\"wp-block-heading\">What&#8217;s needed?<\/h5>\n\n\n\n<ul class=\"wp-block-list\"><li>a functional <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/06\/26\/how-to-set-up-a-kubernetes-cluster\/\">kubernetes cluster<\/a><\/li><li>a functional <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/06\/how-to-install-gitlab-and-work-with-it\/\">gitlab setup<\/a> (make sure to set up <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/08\/how-to-install-and-connect-a-gitlab-runner\/\">runners<\/a> too)<\/li><li>basic knowledge about <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/05\/how-to-build-a-webservice-with-docker\/\">docker and docker file<\/a><br><\/li><\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Let&#8217;s go<\/h5>\n\n\n\n<p>The gitlab container registry has to be enabled, from 12.5 on it is enabled by default.<br>If you would like to put it on it&#8217;s own url, you may set:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gitlab_external_registry=\"name.domain.tld\" in \/etc\/gitlab\/gitlab.rb (for omnibus installation).<\/code><\/pre>\n\n\n\n<p>Build a basic dockerimage with an installed lighttpd (checkout <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/05\/how-to-build-a-webservice-with-docker\/\">docker and docker file<\/a>) <\/p>\n\n\n\n<p>Setup a new project in gitlab and name it webserver, for example (checkout <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/06\/how-to-install-gitlab-and-work-with-it\/\">gitlab setup<\/a>).<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">The Docker image<\/h5>\n\n\n\n<p>Create a Dockerfile with the following content (mkdir dockerfile, cd dockerfile, vi Dockerfile):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Dockerfile for simple Lighttpd Server\nFROM \"gitlab.your.domain:4567\/nikster\/webserver\/lighttpd:latest\"\n\nLABEL maintainer \"yourmail@yourprovider.tld\"\nLabel description \"simple Webserver\"\n\nCOPY lighttpd.conf \/etc\/lighttpd\/\nCOPY start.sh \/usr\/local\/bin\/\n\nCMD [\"\/usr\/local\/bin\/start.sh\"]\n<\/code><\/pre>\n\n\n\n<p>The important parts are:<\/p>\n\n\n\n<p>FROM: it tells docker from where to get the base image (could be dockerhub as well, if you follow my docker tutorial)<br>COPY: we copy the lighttp.conf to it&#8217;s location.<br>This is the part of this setup that is most likely to change often and every time it does, we&#8217;ll commit it, push it <strong>and run it through our pipeline<\/strong> to be deployed in production.<br>Also we copy our own startscript and tell docker to execute it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi lighttpd.conf\n\nserver.modules              = (\n            \"mod_access\",\n            \"mod_alias\",\n            \"mod_accesslog\",\n            \"mod_compress\",\n            \"mod_status\",\n            \"mod_redirect\",\n)\n\nserver.document-root\t\t= \"\/var\/www\/\"\nserver.upload-dirs\t\t= ( \"\/var\/cache\/lighttpd\/uploads\" )\nserver.errorlog            \t= \"\/var\/log\/lighttpd\/error.log\"\nserver.pid-file\t\t\t= \"\/var\/run\/lighttpd.pid\"\nserver.username\t\t\t= \"www-data\"\nserver.groupname\t\t= \"www-data\"\n\nindex-file.names           \t= ( \"index.php\", \"index.html\", \"index.lighttpd.html\" )\n\naccesslog.filename         \t= \"\/var\/log\/lighttpd\/access.log\"\nurl.access-deny            \t= ( \"~\", \".inc\" )\nstatic-file.exclude-extensions = ( \".php\", \".pl\", \".fcgi\" )\n\n## Use ipv6 only if available.\ninclude_shell \"\/usr\/share\/lighttpd\/use-ipv6.pl\"\n\n## virtual directory listings\ndir-listing.encoding        = \"utf-8\"\nserver.dir-listing          = \"enable\"\n\n#### compress module\ncompress.cache-dir          = \"\/var\/cache\/lighttpd\/compress\/\"\ncompress.filetype           = (\"text\/plain\", \"text\/html\", \"application\/x-javascript\", \"text\/css\")\n\n#include_shell \"\/usr\/share\/lighttpd\/use-ipv6.pl \" + server.port\ninclude_shell \"\/usr\/share\/lighttpd\/create-mime.assign.pl\"\ninclude_shell \"\/usr\/share\/lighttpd\/include-conf-enabled.pl\"\n\n$HTTP[\"remoteip\"] =~ \"127.0.0.1\" {\n\talias.url += (\n\t\t\"\/doc\/\" => \"\/usr\/share\/doc\/\",\n\t\t\"\/images\/\" => \"\/usr\/share\/images\/\"\n\t)\n\t$HTTP[\"url\"] =~ \"^\/doc\/|^\/images\/\" {\n\t\tdir-listing.activate = \"enable\"\n\t}\n}\nserver.port\t\t\t= 8080\nserver.bind\t\t\t= \"\"\n#$HTTP[\"host\"] == \"your.server.tld\" {\n#\tdir-listing.activate = \"disable\"\n#        server.document-root = \"\/var\/www\/whatever\/\"\n#        accesslog.filename = \"\/var\/log\/lighttpd\/webserver-access.log\"\n#}\n$SERVER[\"socket\"] == \"127.0.0.1:80\" {\n        status.status-url = \"\/server-status\"\n}<\/code><\/pre>\n\n\n\n<p>This one should work, as you can see it&#8217;s listening on port 8080. <\/p>\n\n\n\n<p>Now create the start script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi start.sh\n\n#!\/bin\/sh\n\n#NK: Source of this script: https:\/\/github.com\/spujadas\/lighttpd-docker\/\n\ntail -F \/var\/log\/lighttpd\/access.log 2>\/dev\/null &amp;\ntail -F \/var\/log\/lighttpd\/error.log 2>\/dev\/null 1>&amp;2 &amp;\n\/usr\/sbin\/lighttpd -D -f \/etc\/lighttpd\/lighttpd.conf\n<\/code><\/pre>\n\n\n\n<p>it will start the server. <\/p>\n\n\n\n<p>We&#8217;ll also create a small test script to do some Q&amp;A in our pipeline:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi script.sh\n\n#!\/usr\/bin\/env bash\n\nset -e\n\necho-run() {\n    echo \"===== Testing if the webserver is running ===== $1\"\n    echo \"$($1)\"\n    echo\n}\n\ndeclare MYHOSTNAME=\"$(hostname)\"\n\necho-run \"\/etc\/init.d\/lighttpd start\"\necho-run \"hostname\"\necho-run \"netstat -antup\"\necho-run \"pwd\"\necho-run \"ls -al --color=auto .\"\necho \"curl -i http:\/\/${MYHOSTNAME}\/\"\n<\/code><\/pre>\n\n\n\n<p>Now may be a good time to commit and push.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">The kubernetes setup<\/h5>\n\n\n\n<p>Kubernetes must be up and running (check out <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/06\/26\/how-to-set-up-a-kubernetes-cluster\/\">kubernetes cluster<\/a>) so we can plug it into our gitlab. <\/p>\n\n\n\n<p>In your Project, klick on:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Operations<\/li><li>Kubernetes<\/li><li>add kubernetes cluster<\/li><li>add existing cluster<\/li><\/ul>\n\n\n\n<p>You will be asked to fill in some information:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Cluster Name &#8211; choose a name you like<\/li><li>api url (find it on your cluster): <\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl cluster-info | grep 'Kubernetes master' | awk '\/http\/ {print $NF}' <\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>CA Certificate:<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get secret &lt;secret name> -o jsonpath=\"{['data']['ca\\.crt']}\" | base64 --decode<\/code><\/pre>\n\n\n\n<p>You&#8217;ll also need a token (if you followed the kubernetes cluster howto, fetch it like this):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')<\/code><\/pre>\n\n\n\n<p>If not or if something does not work, read this: <br>https:\/\/docs.gitlab.com\/ee\/user\/project\/clusters\/add_remove_clusters.html#existing-gke-cluster<\/p>\n\n\n\n<p>OK, now that kubernetes is plugged into gitlab, we need to tell it what services we want to deploy, how they can be accessed, and so on.<br>We do this with yaml files, that we&#8217;ll add to our gitlab project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir manifests \nvi deployment.yaml\n\napiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: __CI_BUILD_REF_SLUG__\n  namespace: kube-system\n  labels:\n    app: __CI_BUILD_REF_SLUG__\n    track: stable\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n      app: __CI_BUILD_REF_SLUG__\n  template:\n    metadata:\n      labels:\n        app: __CI_BUILD_REF_SLUG__\n        track: stable\n    spec:\n      imagePullSecrets:\n        - name: gitlab-admin\n      containers:\n      - name: app\n        image: gitlab.your.domain:4567\/user\/webserver\/webserver:__VERSION__\n        imagePullPolicy: Always\n        volumeMounts:\n        - name: firmware\n          mountPath: \/var\/www\/firmware\n        - name: balance\n          mountPath: \/var\/www\/balance\n        - name: logvol\n          mountPath: \/var\/log\/lighttpd\n        ports:\n        - containerPort: 8080\n        readinessProbe:\n          tcpSocket:\n            port: 8080\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        livenessProbe:\n          tcpSocket:\n            port: 8080\n          initialDelaySeconds: 15\n          periodSeconds: 20\n      volumes:\n      - name: firmware\n        emptyDir: {}    \n      - name: balance\n        emptyDir: {}    \n      - name: logvol\n        emptyDir: {}    \n<\/code><\/pre>\n\n\n\n<p>This will create a deployment object for kubernetes, based on our docker image, with 2 replicas and 3 volumes (in this case of the type empty dir: non persistent storage!).<br>Read more about storage here, if you are interested:  https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/<br>For simplicity the kube-system namespace is used here. <\/p>\n\n\n\n<p>Now, let&#8217;s define the Service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi service.yaml\n\napiVersion: v1\nkind: Service\nmetadata:\n  name: webserver-__CI_BUILD_REF_SLUG__\n  namespace: kube-system\n  labels:\n    app: __CI_BUILD_REF_SLUG__\nspec:\n  type: ClusterIP\n  externalIPs:\n  - 10.88.6.90\n  externalTrafficPolicy: Cluster\n  ports:\n  - nodePort: 31808\n    port: 8080\n    protocol: TCP\n    targetPort: 8080\n  selector:\n    app: __CI_BUILD_REF_SLUG__\n  sessionAffinity: None\n  type: LoadBalancer\nstatus:\n  loadBalancer: {}\n<\/code><\/pre>\n\n\n\n<p>Important parts here are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>type ClusterIP &#8211; the IP the Service should be available at<\/li><li>type LoadBalancer &#8211; as the name already states: Service will be behind the built in loadbalancer<\/li><\/ul>\n\n\n\n<p>Last, but not least we <strong>could<\/strong> create an ingress object (Service would also run without it but one would need a separate IP for every Loadbalancer, ingress routes requests by host- and servicename (URI). <br>Therefore an ingress controller needs to be deployed on kubernetes.<br>There are several: best known are nginx, haproxy and traefik.<br>(This isn&#8217;t necessary to get your first service online but cool, I&#8217;ve played with nginx and haproxy so far).<br>Read about how to deploy an haproxy ingress here: https:\/\/haproxy-ingress.github.io\/docs\/getting-started\/<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: extensions\/v1beta1\nkind: Ingress\nmetadata:\n  name: webserver-__CI_BUILD_REF_SLUG__\n  namespace: kube-system\n  labels:\n    app: __CI_BUILD_REF_SLUG__\n  #annotations:\n   # kubernetes.io\/tls-acme: \"true\"\n   # kubernetes.io\/ingress.class: \"nginx\"\nspec:\n  tls:\n  - hosts:\n    - __CI_BUILD_REF_SLUG__-gitlab.your.domain\n    # the secret used here is an unsigned wildcard cert for demo purposes\n    # use your own or comment this out\n    secretName: tls-wildcard-demo\n  rules:\n  - host: __CI_BUILD_REF_SLUG__-gitlab.your.domain\n    http:\n      paths:\n      - path: \/\n        backend:\n          serviceName: webserver-__CI_BUILD_REF_SLUG__\n          servicePort: 8080\n<\/code><\/pre>\n\n\n\n<p>Time to commit and push and then build the pipeline itself.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">The Pipeline<\/h5>\n\n\n\n<p>Now, we need to glue it all together.<br>Therefore we create our pipeline definition for the Project (make sure this file in the root directory of your project):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi .gitlab-ci.yaml\n\nimage: \"gitlab.your.domain:4567\/nikster\/webserver\/lighttpd:latest\"\n\nbefore_script:\n  - docker login -u gitlab+deploy-token-1 -p &lt;pass> gitlab.your.domain:4567\n\nstages:\n  - test\n  - build\n  - deploy\n\nbefore_script:\n  - apt-get update &amp;&amp; apt-get install -y -o Dpkg::Options::=--force-confold net-tools lighttpd \n\nmy_tests:\n  stage: test\n  script:\n  - echo \"Running my tests in Environment $CI_JOB_STAGE\"\n  - echo \"CI-BUILD-REF-SLUG $CI_BUILD_REF_SLUG\"\n  - .\/script.sh\n\nimage_build:\n  stage: build\n  image: \"gitlab.your.domain:4567\/nikster\/webserver\/lighttpd:latest\"\n  script:\n    - echo \"Entering Environment $CI_JOB_STAGE\"\n    - echo \"CI-BUILD-REF-SLUG $CI_BUILD_REF_SLUG\"\n#    - mkdir \/etc\/docker \n#    - cp daemon.json \/etc\/docker\/daemon.json \n#    - cp docker_default \/etc\/default\/docker \n    - docker info\n    - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} gitlab.your.domain:4567\n    - cat \/etc\/resolv.conf\n    - docker build --no-cache -f dockerfile\/Dockerfile -t gitlab.your.domain:4567\/nikster\/webserver\/webserver:${CI_COMMIT_REF_NAME} .\n    - docker tag gitlab.your.domain:4567\/nikster\/webserver\/webserver:${CI_COMMIT_REF_NAME} gitlab.your.domain:4567\/nikster\/webserver\/webserver:${CI_COMMIT_REF_NAME}\n    - test ! -z \"${CI_COMMIT_TAG}\" &amp;&amp; docker push gitlab.your.domain:4567\/nikster\/webserver\/webserver:${CI_COMMIT_REF_NAME}\n    - docker push gitlab.your.domain:4567\/nikster\/webserver\/webserver:${CI_COMMIT_REF_NAME}\n\ndeploy_live:\n  stage: deploy\n  image: \"gitlab.your.domain:4567\/nikster\/webserver\/webserver:${CI_COMMIT_REF_NAME}\"\n  environment:\n    name: live\n    url: https:\/\/yourkubernetesclusterapi.your.domain\n#environment:\n#  only:\n#    - master\n#    - tags\n#  when: manual\n  script:\n    - echo \"CI_COMMIT_REF_NAME $CI_COMMIT_REF_NAME\"\n    - echo \"Entering Environment $CI_JOB_STAGE\"\n    - echo \"CI-BUILD-REF-SLUG $CI_BUILD_REF_SLUG\"\n    - mkdir ~\/.kube\n    - cp admin.conf ~\/.kube\/admin.conf \n    - export KUBECONFIG=~\/.kube\/admin.conf\n    - kubectl version\n    - cd manifests\/\n    - sed -i \"s\/__CI_BUILD_REF_SLUG__\/${CI_ENVIRONMENT_SLUG}\/\" deployment.yaml ingress.yaml service.yaml\n    - sed -i \"s\/__VERSION__\/${CI_COMMIT_REF_NAME}\/\" deployment.yaml ingress.yaml service.yaml\n    - echo \"VERSION $VERSION\"\n    - kubectl apply -f deployment.yaml\n    - kubectl apply -f service.yaml\n#   - kubectl apply -f ingress.yaml\n#   - kubectl rollout status -f deployment.yaml\n    - kubectl get all,ing -l app=${CI_ENVIRONMENT_SLUG}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>image: which docker image to use<\/li><li>before_script: logs into our docker hub (on gitlab), I found that works best.<br>the second before_script directive updates all packages in the image to their latest version.<\/li><li>stage: here we define our three stages: TEST, BUILD and DEPLOY (maybe better called PROD)<br>In the <strong>TEST STAGE<\/strong> the pipeline executes the basic testscript we wrote to check if the service comes up and is available.<br>If QA is passed the new container is <strong>BUILD<\/strong> and the new image is pushed to our hub.<br>Then it is <strong>DEPLOY<\/strong>ed on kubernetes .<br><br>I&#8217;ve also added lots of debug output to see what the pipeline does.<\/li><\/ul>\n\n\n\n<p>If you commit and push your changes, from now on the pipeline will be triggered on every commit.<br>Fetching the latest image, update it, test if lighttpd runs, build a new image and then deploy a 2x replicated and loadbalanced Service on kubernetes!<br><br>my project now looks like this (everything needed is described here):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1004\" height=\"572\" src=\"https:\/\/blog.nikster.de\/wordpress\/wp-content\/uploads\/2020\/01\/Screenshot-2020-01-25-at-23.32.37.png\" alt=\"\" class=\"wp-image-72\"\/><\/figure>\n\n\n\n<p>Pipelines look like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1205\" height=\"206\" src=\"https:\/\/blog.nikster.de\/wordpress\/wp-content\/uploads\/2020\/01\/Screenshot-2020-01-25-at-23.35.12.png\" alt=\"\" class=\"wp-image-73\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1315\" height=\"548\" src=\"https:\/\/blog.nikster.de\/wordpress\/wp-content\/uploads\/2020\/01\/Screenshot-2020-01-25-at-23.36.05.png\" alt=\"\" class=\"wp-image-74\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1278\" height=\"1385\" src=\"https:\/\/blog.nikster.de\/wordpress\/wp-content\/uploads\/2020\/01\/Screenshot-2020-01-25-at-23.39.17.png\" alt=\"\" class=\"wp-image-75\"\/><\/figure>\n\n\n\n<p>Our deployment is the last of the three: the replicaset.apps\/thingy<br>Have fun playing around with this stuff! I had it.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h4 class=\"wp-block-heading\">Tips<\/h4>\n\n\n\n<p>At some point you might want\/need to use a private <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/06\/how-to-install-gitlab-and-work-with-it\/\">gitlab registry<\/a> for your <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/05\/04\/how-to-build-your-own-docker-image\/\">docker images<\/a>, then you&#8217;ll need <a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2019\/06\/26\/how-to-set-up-a-kubernetes-cluster\/\">kubernetes<\/a> to log into gitlab and pull the image (works with private registries on dockerhub as well), here&#8217;s how to do it:<\/p>\n\n\n\n<p> Check if a serviceaccount exists for your namespace, otherwise create one yourself:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get sa -n webservice-live\nNAME                              SECRETS   AGE\ndefault                           1         9h\nwebservice-live-service-account   1         9h<\/code><\/pre>\n\n\n\n<p>if none exists (better not use default):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vi my-service-account.yml\n\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: webservice-live-service-account\n  namespace: webservice-live\n\nkubectl apply -f my-service-account.yml<\/code><\/pre>\n\n\n\n<p>Now we&#8217;ll need a secret for our private registry, attached to our namespace:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create secret docker-registry gitlab-reg --docker-server='https:\/\/gitlab.my.domain:4567' --docker-username='validprojectusername' --docker-password='Validprojectuserpassword' --docker-email='myaddress@email.tld' -n webservice-live\n\nsecret\/gitlab-reg created<\/code><\/pre>\n\n\n\n<p>check the secret like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get secret gitlab-reg --output=yaml -n webservice-live             \napiVersion: v1\ndata:\n  .dockerconfigjson: eyJhdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlYWVdsMCJ9fX0=\nkind: Secret\nmetadata:\n  creationTimestamp: \"2020-02-27T20:52:45Z\"\n  name: gitlab-reg\n  namespace: webservice-live\n  resourceVersion: \"355279\"\n  selfLink: \/api\/v1\/namespaces\/webservice-live\/secrets\/gitlab-reg\n  uid: 82f9675c-1967-4be9-9a5b-ac1c9e18b09a\ntype: kubernetes.io\/dockerconfigjson<\/code><\/pre>\n\n\n\n<p>.dockerconfigjson object contains the base64 encoded credentials, if you encounter problems, check them like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>root@kubernetes-master1:~# echo \"eyJhdxxxxxxxxxxxxxxxxxxxxxxxxxxxxlYWVdsMCJ9fX0=\" | base64 -d\n{\"auths\":{\"https:\/\/gitlab.my.domain:4567\":{\"username\":\"validgitlabprojectuser\",\"password\":\"validgitlabprojectpassword\",\"email\":\"mymail@email.tld\",\"auth\":\"base64credsagain\"}}}<\/code><\/pre>\n\n\n\n<p>now we may patch the secret into our serviceaccount:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl patch serviceaccount webservice-live-service-account -p '{\"imagePullSecrets\": &#91;{\"name\": \"gitlab-reg\"}]}' -n webservice-live<\/code><\/pre>\n\n\n\n<p>we see that the account now contains the secret named gitlab-reg:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl describe sa webservice-live-service-account -n webservice-live                      Name:                webservice-live-service-account\nNamespace:           webservice-live\nLabels:              &lt;none>\nAnnotations:         &lt;none>\nImage pull secrets:  gitlab-reg\nMountable secrets:   webservice-live-service-account-token-9pdx6\nTokens:              webservice-live-service-account-token-9pdx6\n                     webservice-live-token\nEvents:              &lt;none><\/code><\/pre>\n\n\n\n<p> it&#8217;s usable in a (e.g deployment-) manifest now:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spec:\n      serviceAccountName: webservice-live-service-account\n      containers:\n       - name: webservice\n         image: gitlab.my.domain:4567\/path\/to\/image:__VERSION__\n         ports:\n          - containerPort: 80\n      imagePullSecrets:\n       - name: gitlab-reg<\/code><\/pre>\n\n\n\n<p>technically you&#8217;ll need either <strong>serviceAccountName<\/strong> or <strong>imagePullSecrets<\/strong> in your deployment.yaml, here are both ways.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What&#8217;s a pipeline? In short: A Pipeline helps you to get your code (or in general: service) from Development (stage) to production (stage) in a short time, while providing the ability for automatic tests in a consistent environment. What&#8217;s this about? I&#8221;ll build a pipeline that builds a web server in a docker container, tests &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/blog.nikster.de\/wordpress\/index.php\/2020\/01\/26\/how-to-set-up-a-devops-pipeline-with-gitlab-and-kubernetes\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;How To set up a DevOps Pipeline with gitlab and kubernetes&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,30],"tags":[36,3,14,31,37],"class_list":["post-63","post","type-post","status-publish","format-standard","hentry","category-git","category-kubernetes","tag-devops","tag-docker","tag-gitlab","tag-kubernetes","tag-pipeline","entry"],"_links":{"self":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/63","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=63"}],"version-history":[{"count":7,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/63\/revisions"}],"predecessor-version":[{"id":96,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/63\/revisions\/96"}],"wp:attachment":[{"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=63"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=63"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nikster.de\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=63"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}