<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>secret on Digi Hunch</title><link>https://static.digihunch.com/tag/secret/</link><description>Recent content in secret on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Mon, 12 May 2025 23:28:25 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/secret/index.xml" rel="self" type="application/rss+xml"/><item><title>Getting started with GitHub Actions</title><link>https://static.digihunch.com/2021/05/getting-started-with-github-actions/</link><pubDate>Thu, 27 May 2021 13:52:31 -0400</pubDate><guid>https://static.digihunch.com/2021/05/getting-started-with-github-actions/</guid><description>&lt;p class="wp-block-paragraph"&gt;In my &lt;a class="rank-math-link" href="https://github.com/digihunch/orthweb"&gt;orthweb&lt;/a&gt; &lt;a href="https://static.digihunch.com/projects/"&gt;project&lt;/a&gt;, I had to compile a library on my own. In search for free computing resources I realized that GitHub action can meet all my needs.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ci-cd-pipeline"&gt;CI/CD pipeline&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As a development project grows, there are many operational tasks demanding automation. Prior to pipeline technology, developers used to use &lt;a href="https://en.wikipedia.org/wiki/Make_(software)"&gt;Makefile&lt;/a&gt; to organize command execution locally. Today, its role has declined, but &lt;a href="https://tech.trivago.com/post/2019-12-20-makefiles-in-2019/"&gt;Makefile&lt;/a&gt; is a good choice in certain situations. In most cases though, to offload the build command execution to a shared system, automation engines like Jenkins came around. Then Jenkins evolved into pipelines.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In strict terms, CI pipeline is the build pipeline; and CD pipeline is release pipeline. The two types of pipelines use pretty much the same pool of building blocks, with different purposes. The build pipeline focuses on producing quality artifact in a consistent manner. The release pipelines focus on system stability while deploying an artifact across different environments. Because release pipelines may connect to different environment, it has to deal with various situations. It is very common to have multiple stages in release pipeline, each stage pointing to a different environment (e.g. DEV, TEST and PROD). At workplace both could be loosely referred to as CI/CD pipeline, or even simply pipeline.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A lot of projects provide pipeline capability: BitBucket, Bamboo, TeamCity, Jenkins, Azure DevOps, AWS CodePipeline, TravisCI etc. Since late 2018, GitHub also joined the game with GitHub actions. It is openly &lt;a class="rank-math-link" href="https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#:~:text=GitHub%20Actions%20usage%20is%20free,is%20controlled%20by%20spending%20limits."&gt;free&lt;/a&gt; for public repositories, and has a free tier for private repositories. It executes task as defined in .github/workflow/action.yaml in the code project. I will take my own project as an example.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-runners"&gt;Runners&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;You can run jobs in self-hosted runners or GitHub managed runners, similar to other pipeline solutions (e.g. self-hosted agent vs managed agent from Azure DevOps). The &lt;a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#github-hosted-runners" class="rank-math-link"&gt;GitHub hosted runners&lt;/a&gt; only have three operating systems to support: Windows, Ubuntu and MacOS. The Ubuntu and Windows runners are built from Standard_DS2_v2 VMs in Microsoft Azure. They are pre-installed with a &lt;a href="https://github.com/actions/virtual-environments" class="rank-math-link"&gt;virtual environment &lt;/a&gt;with packages required for common build tasks. The same virtual environment is also used in hosted agents by Azure DevOps. While they are free and you can elevate privilege on the runner, you cannot SSH or RDP to it for further troubleshooting. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners" class="rank-math-link"&gt;self-hosted runners&lt;/a&gt; require users to manage the instance on their own, including configuring virtual environment, installing &lt;a href="https://github.com/actions/runner" class="rank-math-link"&gt;GitHub Action Runner&lt;/a&gt;, etc.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-workflow-file"&gt;Workflow file&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Most pipeline declaration uses YAML or JSON, such as &lt;a href="https://www.jenkins.io/doc/book/pipeline/jenkinsfile/" class="rank-math-link"&gt;Jenkinsfile&lt;/a&gt;, AWS &lt;a href="https://docs.aws.amazon.com/code-samples/latest/catalog/code-catalog-cloudformation-codepipeline.html" class="rank-math-link"&gt;CodePipeline&lt;/a&gt;. GitHub refers to an automation process as a &amp;#8220;workflow&amp;#8221; and you can program the workflow in YAML (.github/workflow/action.yaml). Here is the &lt;a href="https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions" class="rank-math-link"&gt;reference&lt;/a&gt; and an example with environmental variable and versioning: &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;script src="https://gist.github.com/digihunch/e6ed668872c5b0506d25f638ff70727e.js"&gt;&lt;/script&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The handling of environment is documented &lt;a href="https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable" class="rank-math-link"&gt;here&lt;/a&gt;. There are a lot of custom actions available in GitHub &lt;a href="https://github.com/marketplace" class="rank-math-link"&gt;Marketplace&lt;/a&gt;. For example, the versioning in the above example, uses an &lt;a href="https://github.com/marketplace/actions/nuget-build-number-generator" class="rank-math-link"&gt;action&lt;/a&gt; by &lt;a href="https://einaregilsson.com/a-github-action-for-generating-sequential-build-numbers/" class="rank-math-link"&gt;Einar Egilsson&lt;/a&gt;, which is open source itself.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-example-pipeline"&gt;Example pipeline&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;My example &lt;a href="https://github.com/digihunch/orthweb/blob/67542d9329be36e3b8ca895c8b71805c9711aaa3/.github/workflows/action.yml" class="rank-math-link"&gt;pipeline&lt;/a&gt; consists of two phases: &lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Build Library: spin up a docker container to build source code, and publish the artifact&lt;/li&gt;&#10;&lt;li&gt;Publish Image: add the artifact to an existing Docker image, and publish the result as my own image.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The status of the pipeline is also open, and can be found &lt;a href="https://github.com/digihunch/orthweb/actions" class="rank-math-link"&gt;here&lt;/a&gt;. The retention period of artifact is 90 days by default but can be &lt;a href="https://docs.github.com/en/actions/reference/usage-limits-billing-and-administration#artifact-and-log-retention-policy" class="rank-math-link"&gt;customized&lt;/a&gt;. To persist the artifact, I add it to my own Docker image and publish it to &lt;a href="https://hub.docker.com/r/digihunch/orthanc-plugin" class="rank-math-link"&gt;DockerHub&lt;/a&gt;, hence the second phase.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1152" height="724" src="https://static.digihunch.com/wp-content/uploads/2021/05/image-1.png" alt="" class="wp-image-2299"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt; When building the second phase, I need to generate secret from my DockerHub account and store that &lt;a href="https://docs.github.com/en/actions/reference/encrypted-secrets" class="rank-math-link"&gt;encrypted secrets&lt;/a&gt; in GitHub settings, so that the secret value can be referenced in workflow file.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Failures in Actions are displayed in error steps and by default the rest of the steps are skipped. &lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="968" height="624" src="https://static.digihunch.com/wp-content/uploads/2021/05/image-2.png" alt="" class="wp-image-2301"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I use the &lt;strong&gt;&lt;a class="rank-math-link" href="https://github.com/marketplace/actions/docker-build-push-action"&gt;Docker build &amp;amp; push plugin&lt;/a&gt;&lt;/strong&gt; to build and push my own docker image to DockerHub. Apart from DockerHub as my choice, GitHub also has its own artifactory GitHub &lt;a class="rank-math-link" href="https://github.com/features/packages"&gt;Packages&lt;/a&gt; with a small free tier. It supports NPM, Docker, Maven, Gradle, etc. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Triggers of Action&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Most of the times, GitHub action are triggered upon commit to main branch of the repo. In GitHub, this is known as a &lt;a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch"&gt;workflow_dispatch&lt;/a&gt; event. This is not the only event that can trigger GitHub action. All the available events are listed &lt;a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#available-events"&gt;here&lt;/a&gt; on its documentation. This makes it very flexible to trigger action at many points in the workflow. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One example is to trigger GitHub action during PR review. When a developer opens a PR with a few commits in the proposed branch, the PR can preemptively check linting, style, etc and even build the application. These activities can also be defined in a GitHub action manifest with &lt;strong&gt;pull_request&lt;/strong&gt; as triggering event.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Troubleshooting&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In general, it is painful to troubleshoot activities happening inside of runners. I often had to write a few steps for the sake of printing variables, and trigger a run to see what their value is. This requires a lot of time especially when I have to wait for available runners. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To help troubleshooting pipeline runs there is an open-source utility called &lt;a href="https://github.com/nektos/act"&gt;act&lt;/a&gt;. You can run GitHub actions locally from a Docker container on your MacBook. You can deliver environment variables and secrets via files. If you ever need to troubleshoot the runner environment, you have the option to connect to the Shell environment inside of the runner container. This tool is extremely helpful.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-closing-remarks"&gt;Closing remarks&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;GitHub action really makes the CI/CD pipeline capability available to any developers who stores their code on GitHub. GitHub expands from a code repository solution to a full CI/CD solution with a free tier sufficient for personal projects.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/05/secure-web-application-deployment/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Secure web application deployment&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/06/kubernetes-storage-explained/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kubernetes Storage Explained – from in-tree plugin to CSI&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Secure web application deployment</title><link>https://static.digihunch.com/2021/05/secure-web-application-deployment/</link><pubDate>Sun, 16 May 2021 15:19:41 -0400</pubDate><guid>https://static.digihunch.com/2021/05/secure-web-application-deployment/</guid><description>&lt;p class="wp-block-paragraph"&gt;In Nov 2020, I created &lt;a href="https://github.com/digihunch/orthweb/tree/2181001e29b0da5fd55f51a6dc2a522d3f83aee6" class="rank-math-link"&gt;OrthWeb&lt;/a&gt; project, a deployment of Orthanc&amp;#8217;s server. Orthanc is a DICOM viewer and repo shipped in Docker container. In the &lt;a href="https://static.digihunch.com/2020/11/medical-imaging-web-server-deployment-pipeline/" class="rank-math-link"&gt;deployment project&lt;/a&gt;, I use Terraform to provision infrastructure, including a managed PostgreSQL instance, an EC2 instance for docker runtime, and the init script to bring up the web service. I whipped up the project for a demo, and skipped some security configurations. For example, the password was stored in clear text in Terraform configuration. The web certificate is stored in the repository. I recently had some time to fix that. My effort leads up to the conclusion that this requires a better platform (i.e. managed Kubernetes cluster). So I wanted to note down how I got there.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Secret store&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In AWS, both parameter store and secret manager can act as secret store. Secrets manager comes at higher cost but some additional features, such as built-in password generator, secret rotation, and cross-account access. We use Secret Manager but we generate password within Terraform because we need to specify password during database provisioning. Secret store requires certain special characters to be eliminated. Terraform can specify the special characters allowed. For EC2 instance to pull from secret manager, the following entities are needed:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;A secret store&lt;/li&gt;&#10;&lt;li&gt;A VPC endpoint to expose secret store to subnet via private route. &lt;/li&gt;&#10;&lt;li&gt;The VPC endpoint needs its own security group&lt;/li&gt;&#10;&lt;li&gt;The instance profile of the EC2 instance must contain an IAM role to get secret value&lt;/li&gt;&#10;&lt;li&gt;The security group of EC2 instance needs to allow traffic to secret store&lt;/li&gt;&#10;&lt;li&gt;The script from EC2 instance uses VPC endpoint&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This is a common pattern for interaction between computing object and VPC endpoint. The details are in compute.tf, network.tf, secgrp.tf and secret.tf. The secret name needs to be partially randomized to avoid naming conflict with deactivated secrets.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large"&gt;&lt;img loading="lazy" decoding="async" width="623" height="323" src="https://static.digihunch.com/wp-content/uploads/2021/05/secmgr.png" alt="" class="wp-image-2250"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Passing Secret to container&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is an example CLI command to pull secret:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ aws secretsmanager get-secret-value --secret-id DatabaseCreds51c1db4172ae9c54 --query SecretString --output text --endpoint-url https://vpce-0897b168cf1c60df2-khx32o7f.secretsmanager.us-east-1.vpce.amazonaws.com | jq -r .password&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The connection is made via private network route (whether the instance is in public or private subnet). Traffic is encrypted in TLS. Once in the operating system, the secret is available as standard output and can be stored to file, or saved in environment variable. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;My first attempted approach is docker&amp;#8217;s secret store and config so that I do not have to store secret in plain text on the file system. I eventually give up this approach due to several hiccups. First, secret and config are part of Docker swarm service. So it requires initializing docker swarm before I could port in the secret, with the following command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker swarm init&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo mdbuser123 | docker secret create db_un -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo m1p@ssw0rd | docker secret create db_pw -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ echo 10.2.32.41 | docker config create db_ep -&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The content of the secret and config are presented as files to the container file system at different locations, as can be verified this way:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker service create --name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt; --secret&lt;span style="color:#f92672"&gt;=&lt;/span&gt;db_un --secret&lt;span style="color:#f92672"&gt;=&lt;/span&gt;db_pw --config&lt;span style="color:#f92672"&gt;=&lt;/span&gt;db_ep redis:alpine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker container ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ docker exec -it c8ed2a278ca8 sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat /db_ep&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat /run/secrets/db_un&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat /run/secrets/db_pw&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This is a great way to pass secret and config to container applications. However, since the values are stored as content of file, the main application must be able to load file content as its own configuration value. In my specific scenario, the application expects explicit value in its &lt;a href="https://orthanc.uclouvain.be/book/users/configuration.html" class="rank-math-link"&gt;configuration file&lt;/a&gt;, or environment variable.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the other hand, Docker &lt;a href="https://techbeacon.com/devops/how-keep-your-container-secrets-secure" class="rank-math-link"&gt;document&lt;/a&gt; states that docker secrets do not set environment variables directly. this was a conscous decision, because env var can unintentionally be leaked between containers. In other word I could present secrets as files but the application cannot use it. There is potentially a workaround &lt;a href="https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab" class="rank-math-link"&gt;here&lt;/a&gt; which is great function wise but an additional layer of complexity.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Moreover, I later discovered that this isn&amp;#8217;t even a viable approach if I use docker compose. This is because I must declare those entries from secret store or config store as &lt;a href="https://docs.docker.com/compose/compose-file/compose-file-v3/#configs" class="rank-math-link"&gt;external&lt;/a&gt;, and external secrets are not even available to containers created by docker-compose. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With reluctance, I store the config and secret keys and values to a file, and use the &lt;a href="https://docs.docker.com/compose/environment-variables/#the-env-file" class="rank-math-link"&gt;env_file&lt;/a&gt; section in docker compose to import them as environment variables. The application can pick up environment variables as configuration values.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;X509 Certificate&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We use a self-signed X509 certificate, along with the private key. The &lt;a href="https://orthanc.uclouvain.be/book/faq/https.html#securing-orthanc-using-self-signed-certificate" class="rank-math-link"&gt;creation&lt;/a&gt; is straightforward. However, when I tested on Mac, the browser does not load the page for &lt;a href="https://support.apple.com/en-us/HT210176" class="rank-math-link"&gt;this&lt;/a&gt; reason. Since macOS 10.15, the certificate requires several extensions: ExtendedKeyUsage, Subject alternative names and DNS name. The native openssl from the operating system is outdated (v 1.0.2) and I had to install openssl11 package and create it as follows:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl11 req -x509 -nodes -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -newkey rsa:2048 -keyout /tmp/private.key -out /tmp/certificate.crt -subj /C&lt;span style="color:#f92672"&gt;=&lt;/span&gt;CA/ST&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Ontario/L&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Waterloo/O&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Digihunch/OU&lt;span style="color:#f92672"&gt;=&lt;/span&gt;Imaging/CN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;digihunch.com/emailAddress&lt;span style="color:#f92672"&gt;=&lt;/span&gt;info@3.237.97.93 -addext extendedKeyUsage&lt;span style="color:#f92672"&gt;=&lt;/span&gt;serverAuth -addext subjectAltName&lt;span style="color:#f92672"&gt;=&lt;/span&gt;DNS:orthweb.digihunch.com,DNS:digihunch.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The Mac uses libreSSL backed openSSL utility and can achieve the same with slightly different command line argument.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Next Step&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The limitation with passing secret concerns me and I&amp;#8217;m looking to move to managed Kubernetes platform where &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables" class="rank-math-link"&gt;secrets&lt;/a&gt; can be ported to environment variable of Pods. We can also consider &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html" class="rank-math-link"&gt;ECS&lt;/a&gt; in AWS which allows to inject sensitive data from secret manager to container. &lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/04/preparing-certified-kubernetes-administrator-exam/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Certified Kubernetes Administrator (CKA) Exam&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/05/getting-started-with-github-actions/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Getting started with GitHub Actions&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Basic Resource Object in Kubernetes 2 of 2</title><link>https://static.digihunch.com/2021/02/basic-resource-object-in-kubernetes-2-of-2/</link><pubDate>Mon, 08 Feb 2021 21:02:16 -0400</pubDate><guid>https://static.digihunch.com/2021/02/basic-resource-object-in-kubernetes-2-of-2/</guid><description>&lt;p class="wp-block-paragraph"&gt;We continued from previous posting about resource object, starting from storage related ones. &lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/vol-128.png" alt=""/&gt;&lt;figcaption&gt;Volume&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In Kubernetes, we use the term volume to refer to a section storage device. There are many plugins, compliant to Container Storage Interface (CSI), to allow heterogeneous storage resources to be surfaced as volumes in Kubernetes. CSI allows storage driver to operate in parallel to the main Kubernetes code tree. Any driver that complies with CSI would work with any orchestration platform that requires CSI, such as Docker Swarm, Kubernetes. Three main resources in the storage system are: PV (persistent volumes), PVC (persistent volume claims), and SC (storage classes).&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/pv-128.png" alt=""/&gt;&lt;figcaption&gt;Persistent Volume&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Persistent Volumes (PV) allows you to map external storage onto the Kubernetes cluster. It is a representation of the external storage on the cluster. A single external storage volume can only be represented by a single PV. For example, you cannot have a 50GB external volume that has two 25GB PVs each representing half of it.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;PV can be mounted in three options:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;RWO (ReadWriteOnce): allows single PVC to mount. This is common for block device.&lt;/li&gt;&lt;li&gt;RWM (ReadWriteMany): allows multiple PVCs to bind as read and write. This is common for file and object level access.&lt;/li&gt;&lt;li&gt;ROM (ReadOnlyMany): allows multiple PVCs to bind as read only. Think of it along the lines of ISO media.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that a PV can only be opened in one of the modes above. All connecting PVC (if multiple are allowed) will use that mode.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/pvc-128.png" alt=""/&gt;&lt;figcaption&gt;Persistent Volume Claim&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Persistent Volume Claims (PVC) act like tickets that authorize applications (Pods) to use a PV. Once a Pod has the PVC, it can bind the respective PV as a volume. You need to specify PV name when declaring a PVC to associate them. Pods do not act directly on PVs, they always act on the PVC object that is bound to the PV. When a PVC is released, two actions can be configured in the policy: Delete and Retain. The delete policy will delete the PV as well as associated storage resource on the external storage system. The retain policy will keep the associated PV object on the cluster as well as any data stored on the associated external assets.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The spec section of PVC object declaration must match the fields in the corresponding PV it binds to. For example access modes, capacity and storage class name.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/sc-128.png" alt=""/&gt;&lt;figcaption&gt;Storage Class&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Storage classes allow you to define different classes (or tiers) of storage using an external provisioner such as aws-ebs. This works well with cloud storage provider. As long as the plugin for storage backend is available, you can configure as many StorageClass object as you need, and even specify to encrypt them. Storage classes create PV dynamically, so you will need to create PVC object that reference the newly created storage class, in order to use cloud storage.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The whole purpose of storage class is to create PVs dynamically, for various storage backend/plugin. You just create the StorageClass object and use a plugin to tie it to a particular type of storage on a particular storage back-end. When matching PVCs appear, the StorageClass dynamically creates the required volume on the back-end storage system.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If a cluster has a default storage class, you can deploy a Pod using just PVC with PodSpec, without explicitly declare storage class per Pod. However, this is not recommended in production.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/cm-128.png" alt=""/&gt;&lt;figcaption&gt;ConfigMaps&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With modern application it is a good practice to decouple configurations from application execution environment. They are stored separately but brought together at runtime. ConfigMap (CM) allows you to store configuration data outside of a Pod, and dynamically inject the configuration data into a Pod at runtime. ConfigMaps are essentially key/value pairs, and each key/value pair is called an entry.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Once data is stored in a ConfigMap, it can be injected into containers at run-time via one of the three methods:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;environment variables: updates to ConfigMap is not updated &lt;/li&gt;&lt;li&gt;arguments to the container&amp;#8217;s startup command (very limited)&lt;/li&gt;&lt;li&gt;files in a volume (most flexible): requires creating a ConfigMap volume in the Pod template and mounting. Eateries in the ConfigMap will appear in the container as individual files. You can make changes to entries after a container is deployed, and the change is seen in the file.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The application is unaware that the data originally came from a ConfigMap. Also note that ConfigMap is not to store sensitive data.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/secret-128.png" alt=""/&gt;&lt;figcaption&gt;Secret&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Kubernetes Secrets let you store and manage sensitive information, such as passwords, OAuth tokens, and ssh keys. Storing confidential information in a Secret is safer and more flexible than putting it verbatim in a Pod definition or in a container image.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The name of a Secret object must be a valid DNS subdomain name. A Secret can be used with a Pod in three ways:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;As files in a volume mounted on one or more of its containers.&lt;/li&gt;&lt;li&gt;As container environment variable.&lt;/li&gt;&lt;li&gt;By the kubelet when pulling images for the Pod.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/ing-128.png" alt=""/&gt;&lt;figcaption&gt;Ingress&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Ingress manages manages external access to the services in a cluster, typically HTTP. It may provide load balancing, SSL termination and name-based virtual hosting. Also, you must have an Ingress controller to satisfy an Ingress. Only creating an Ingress resource has no effect.You can choose from a number of Ingress controllers. Nginx is a common flavour.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/limits-128.png" alt="" width="128" height="124"/&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;By default, containers run with unbounded compute resources on a Kubernetes cluster. With resource quotas, cluster administrators can restrict resource consumption and creation on a namespace basis. Within a namespace, a Pod or Container can consume as much CPU and memory as defined by the namespace&amp;#8217;s resource quota. There is a concern that one Pod or Container could monopolize all available resources. A LimitRange is a policy to constrain resource allocations (to Pods or Containers) in a namespace.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A LimitRange provides constraints that can:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Enforce minimum and maximum compute resources usage per Pod or Container in a namespace.&lt;/li&gt;&lt;li&gt;Enforce minimum and maximum storage request per PersistentVolumeClaim in a namespace.&lt;/li&gt;&lt;li&gt;Enforce a ratio between request and limit for a resource in a namespace.&lt;br&gt;Set default request/limit for compute resources in a namespace and automatically inject them to Containers at runtime.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://github.com/kubernetes/community/raw/master/icons/png/resources/labeled/quota-128.png" alt=""/&gt;&lt;figcaption&gt;Resource Quotas&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When several users or teams share a cluster with a fixed number of nodes, there is a concern that one team could use more than its fair share of resources. Resource quotas are a tool for administrators to address this concern.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A resource quota, defined by a ResourceQuota object, provides constraints that limit aggregate resource consumption per namespace. It can limit the quantity of objects that can be created in a namespace by type, as well as the total amount of compute resources that may be consumed by resources in that namespace.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2021/01/a-shallow-dive-into-artificial-intelligence/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;A shallow dive into Artificial Intelligence&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2021/02/interpret-census-data-from-statistics-canada/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Census Data from Statistics Canada&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>