# Question
Title: Can I get dependencies.child-chart.version from Helm template?
I have this tree:

```
 environments
 ┣ staging
 ┃ ┣ Chart.yaml
 ┃ ┗ values.yaml
 services
 ┣ my-service
 ┃ ┣ helm
 ┃ ┃ ┣ templates
 ┃ ┃ ┃ ┣ deployment.yaml
 ┃ ┃ ┣ Chart.yaml
 ┃ ┃ ┗ values.yaml

```

`environments/staging/Chart.yaml` look like this:

```
apiVersion: v2
name: staging
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.0.0"
dependencies:
  - name: my-service
    repository: file://../../services/my-service/helm
    version: 79947968d75f9b728b321b070d12eaacd12636ca-SNAPSHOT

```

`environments/staging/values.yaml` look like this:

```
my-service:
  image:
    tag: 79947968d75f9b728b321b070d12eaacd12636ca-SNAPSHOT

```

`services/my-service/helm/templates/deployment.yaml` look like this:

```
...
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
...

```

There is a way to access to `dependencies.my-service.version` from my "child" deployment template, with something like this ?

```
        image: "{{ .Values.image.repository }}:{{ .Chart.Dependencies.my-service.version }}"

```

If not (what I guess), do you please have tips to achieve this ?

# Answer
> 1 votes
From the docs

> A subchart is considered "stand-alone", which means a subchart can never explicitly depend on its parent chart. For that reason, a subchart cannot access the values of its parent. A parent chart can override values for subcharts. Helm has a concept of global values that can be accessed by all charts.

I believe the best approach will be to maintain any shared values under the `global` section

---
Tags: helm, kubernetes-helm
---


# Question
Title: Checkout specific ref in Azure Pipeline from private GitHub
I'm facing a problem when trying to use a parameter in my resources.

```
parameters:
- name: MyVersion
  default: "0.0.0"

resources:
  repositories:
  - repository: other
    type: github
    name: mycompany/project
    #Ref with parameter is not allowed
    ref: refs/tags/tag_${{parameters.MyVersion}}
    endpoint: mygithub

```

While this could potentially help, it doesn't work for me because I'm using GitHub. How do I do the same thing with GitHub?

I tried

```
- checkout: git://mycompany/project@refs/tags/tag_${{parameters.MyVersion}}

```

But it tells me "mycompany" doesn't exist. Which makes sense because mycompany is on GitHub and not in Azure DevOps. How do I help Azure DevOps find it? Also, this is a private project that requires authentication for checkout.

# Answer
> 0 votes
Thanks to @M Karimi's suggestion in comments I ended up doing a manual checkout from github with PAT

```
  - checkout: none
  - script: |
    git clone https://$(GITHUBPAT)@github.com/mycompany/project.git
    git checkout refs/tags/tag_${{parameters.MyVersion}}

```

---
Tags: azure-devops, azure-pipelines
---


title: integrate sonarqube with kubernetes

text:
# Question
Title: integrate sonarqube with kubernetes
I am trying to integrate sonarqube on kubernetes , my sonarqube service is up and running in when i do "kubectl get services". but i am unable to fetch that url i.e. (Poratal access url). For deployment purpose i used sonar image which is present inside docker hub https://hub.docker.com/\_/sonarqube\[!\[enter image description here\]\]

# Answer
Assuming you created your `sonarqube` Service in the `default`namespace, and using SonarQube default ports, your portal URL would be `http://sonarqube.default.svc:9000`.
> 1 votes

---
Tags: kubernetes, azure-devops, azure, dockerhub, sonarqube
---


# Question
Title: How can I get the Docker target platform inside the Build Environment / Dockerfile
I'm doing multi-platform builds with buildx and would like to know if there is a way to determine what platform is currently being build so I can avoid certain steps for certain environments.

For example, something like...

```
# No DOSEMU outside amd64
RUN if [ "$DOCKER_PLATFORM" = "amd64" ]; then \
      apt install dosemu \
    fi

```

# Answer
> 3 votes
This is typically done with a script, not the Dockerfile. The script (perhaps in bash or python) can run at build time to determine what environment it is in, and act accordingly. This can be included in the `RUN` command, but it risks becoming quite complex and difficult to read in the Dockerfile. Furthermore, each additional `RUN` or `CMD` entry in the Dockerfile adds a layer to the image, which is considered bad practice.

This script can instead take the arguments `BUILDPLATFORM` and `TARGETPLATFORM` as suggested in the buildx docs, which would make more declarative. Instead of discovering the target, you would declare it (and write your script accordingly), so that the user understands exactly what happens without having to look inside the build.

# Answer
> 1 votes
I would just have a base script that have the things in common for most of the platform like base\_install.sh

Then I would have multiple dockerfiles that can use this base script, an example for your amd64 dockerfile DockerfileAMD64:

```
FROM mybase64image

RUN ./base_install.sh
RUN apt-get install specific64things -y

```

and you can build it with:

```
docker build -f DockerfileAMD64

```

That way you can version control these files without duplicating code between the dockerfiles.

# Answer
> 1 votes
One other option is to use `TARGETPLATFORM` as mentioned but with multistage Dockerfile.

If there's no complex logic apart from a few different steps (between targets), this allows to keep everything in the Dockerfile (and a single one).

```
FROM alpine:3.16 as main-linux-armv7
# do whatever is different on linux/arm/v7

FROM alpine:3.16 as main-linux-amd64
# do whatever should be for linux-amd64

FROM main-linux-amd64 as main-linux-arm64
# linux-arm64 is the same as linux-amd64 but every target needs to be defined

FROM main-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}
# main / final stage

```

---
Tags: docker, dockerfile, bash
---


# Question
Title: Is it possible to create multiple tags out from docker-compose?
While creating a CI/CD via Azure Devops, my goal is to push two tags to the artifactory:

1. latest
2. build version (For example 1.0.X)

My docker-compose looks like:

```
version: '3.4'

services:
    mycontainer:
        image: ${Image}:${Tag}
        build:
            context: .
            dockerfile: */Dockerfile
    rabbitmq:
        ...

```

The yml related steps are:

```
variables:
- name: Tag
  value: '1.0.1'
- name: 'Image'
  value: 'myartifactory/myrepo/mycontainer'

- task: DockerCompose@0
  displayName: 'Docker-Compose up data source'
  inputs:
    dockerComposeFile: 'docker-compose.yml'
    dockerComposeFileArgs: |
      Image=$(Image)
      Tag=$(Tag)
    action: 'Run a Docker Compose command'
    dockerComposeCommand: 'up --build -d'

```

This step successfully creates this result and I'm able to successfully push the 1.0.1's tag to artifactory:

```
Successfully built ############
Successfully tagged myartifactory/myrepo/myproject:1.0.1

- task: ArtifactoryDocker@1
  displayName: 'Push tagged image to artifactory'
  inputs:
    command: 'push'
    artifactoryService: '...'
    targetRepo: '...'
    imageName: '$(DockerImage):$(Tag)'

```

Now, to push the `latest` I need to copy paste these two steps again:

```
- task: DockerCompose@0
  displayName: 'Docker-Compose up data source'
  inputs:
    dockerComposeFile: 'docker-compose.yml'
    dockerComposeFileArgs: |
      Image=$(Image)
      Tag=latest
    action: 'Run a Docker Compose command'
    dockerComposeCommand: 'up --build -d'

- task: ArtifactoryDocker@1
  displayName: 'Push tagged image to artifactory'
  inputs:
    command: 'push'
    artifactoryService: '...'
    targetRepo: '...'
    imageName: '$(DockerImage):latest'

```

Is it possible to tag the `latest` tag together with the `1.0.1` tag and push them together? Because docker-compose up the project with latest again takes a lot of time.

I'm trying also to avoid using script step to run `docker tag ...` to re-tag the image.

# Answer
Wouldn't this be better using docker build? Not docker compose? I'm pretty sure compose is used to spin up things together, rather than your use case. In which case, yes build supports many tags
> 1 votes

---
Tags: docker, docker-compose, azure-devops, continuous-deployment
---


# Question
Title: Docker Push Container to Azure ACR "unauthorized: authentication required"
What is going on here? This should work.

```
$ az logout
$ az login
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code FW....C to authenticate.
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "[redacted]",
    "id": "[redacted]",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Azure subscription 1",
    "state": "Enabled",
    "tenantId": "[redacted]",
    "user": {
      "name": "[redacted]",
      "type": "user"
    }
  }
]
$ az account set -s [subscription id redacted]
$ az acr login --name arcticacr
Login Succeeded
$ docker push ArcticaCR.azurecr.io/sftp01/sftptest:0.02
The push refers to a repository [ArcticaCR.azurecr.io/sftp01/sftptest]
b152ea134f5f: Preparing
d799cb5f12bf: Preparing
6b4e8c931236: Preparing
6f4c91ca60bd: Preparing
86eecfa8066e: Preparing
unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information.

```

I'm logged in as the owner of this registry (per IAM). I should be authorized to do anything. Admin user is enabled under Access keys, even though I'm not using those.

# Answer
The image name needs to be in all lowercase. You can't just change the push command to lowercase.

```
$ docker build -t arcticacr.azurecr.io/sftp01/sftptest:0.02 -f Dockerfile .
$ az login
$ az acr login --name arcticacr
$ docker push arcticacr.azurecr.io/sftp01/sftptest:0.02

```
> 1 votes

---
Tags: docker, azure-devops, azure-pipelines
---


# Question
Title: K8s cluster not deploying deployments across all the nodes
I am a beginner in kubernetes. I have a cluster running with 4 nodes. All the nodes are currently running fine. They are not tainted, or drained. Every time I deploy a deployment it will only deploy it across 2 nodes instead of 4 nodes. I am trying to look for kube-scheduler logs, but because I am using Oracle Cloud OKE service (kubernetes service for Oracle cloud). They don't make kube-scheduler logs available to customers. What tests or what verifications do I need to do?

# Answer
If you want to place a pod on each node you can use DaemonSet. DaemonSets are configured to distribute the application to each node. For detailed information;

https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/

You can find out if DaemonSet is what you need by looking specifically at this title;

https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#deployments
> 2 votes

# Answer
The scheduler placing your pods on one or two nodes, until they're out of resources, could be a "normal" behavior depending on your cluster scheduler policy.

You could try to use an antiAffinity rule, or a topologySpreadConstraints, placing your pods on all 4 nodes.

The following sample, from Kubernetes docs, would use topology key 'kubernetes.io/hostname', which should spread your pods on different nodes:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: kubernetes.io/hostname

```

The `requiredDuringSchedulingIgnoredDuringExecution` would prevent the Kubernetes scheduler from ever starting a replicas on a node that already has a Pod that belongs to your deployment.

We could do something similar with a `topologySpreadConstraints`:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: web-store

```
> 1 votes

---
Tags: kubernetes, deployment
---


# Question
Title: How are containers secured with MACVLAN networks?
Containers cannot be connected both to an internal bridge and to the host network at the same time, according to this question. However, this is what I need; I want a set of containers to be connected both to a Swarm overlay network for inter-container communication (or a different solution if necessary, like Weave), and also to the host's network, without NAT, to expose a service. Thus, for the container to expose its service, the only option I am aware of is to use a macvlan network.

Side note: using a Swarm service without the routing mesh (there will only be one container/service per host, and requests to that host should always be served by the container/service on that host) would work, except my understanding is that a published port will go through NAT. This is undesireable.

It appears that a container exposed through a macvlan network is completely exposed and cannot be firewalled off (I read that the macvlan network is independent of the host's network stack, somehow, and can't be firewalled by the host - if you have a source for this, please link it). It would be possible to limit the attack surface by using the smallest possible image, and be very careful about setting bind addresses for services on the container, but this doesn't replace a firewall.

So, assuming the preceding three paragraphs aren't drastically incorrect, what is the recommended way to securely expose a container on a macvlan network?

# Answer
> 0 votes
The referenced question deals with docker containers being attached to both a bridge and the host network at the same time.

However, to expose a service, you publish your service typically via dockers ingress rather than host most networking so this is rarely an issue.

i.e. the following compose fragment is legal:

```
services:
  my-api:
    image: foo
    networks:
    - overlay1
    - bridge1
    ports:
    - 9090:8080

```

Wheras this fragment is illegal:

```
services:
  my-api:
    image: foo
    # docker compose host mode networking.
    network_mode: host
    networks:
    - overlay1
    - bridge1
    - hostent
    ports:
    # docker swarm can publish a port on a host. This should work
    - target: 80
      published: 8080
      protocol: tcp
      mode: host

networks:
  # A different swarm compatible take on --net:host
  # Also can't be mixed with ingress networking.
  hostnet:
    external: true
    name: host

```

---
Tags: docker, containers, networking, security, docker-swarm
---


# Question
Title: Terraform organising modules/code for multiple projects
I'm fairly new to TF and wonder how people are structuring Terraform for bigger infrastructure. We are moving our infrastructure to Terraform bit by bit. I'm curious how people are approaching that.

Let's assume we have:

* Cloudfront for our API
* API implementation using bunch of AWS Lambdas
* legacy service EC2 hosted backed by MySQL
* lambdas are using legacy service and DynamoDB to fulfill requests

How would you go about and structure Terraform for project like that? Would you put all into one Terraform or split them? If so what's your approach to split TF code? by context?

We also want to move our punch of API lambdas to CI/CD. They are split into multiple code repos and we would like to Terraform them as well. How to link TF for each Lambda with the TF for the rest of infrastructure?

# Answer
Sorry for adding a direct answer, I cannot add comments still.

So from what I have worked with and especially in companies that already had legacy infrastructure with legacy Terraform, that was not well written, what I would first suggest:

1. Read the book Terraform: Up & Running, 2nd Edition Link, it helped me a lot!

* It will give you an idea of how to structure your Terraform and other amazing things. There is also a git repo for this book:GitHub

2. Create modules, as much as you can.

* You can create a module for Cloudfront for example, that can later be reused in other environments.

3. Don't use one state file. Split when needed the state file, for example, if you have EC2 instances that use a ec2.tfstate and you have an EKS cluster, don't use them in the same state, create an eks.tfstate file that will be only for the EKS. Another thing is, don't use local tfstate files. If you are in AWS for example create an S3 that is split by live/ /staging/ legacy/ or whatever fits the needs structure and in there put your ec2,eks,cloudwatch or other state files.
4. You can split your terraform in multiple repos if needed, but being in one repo, split into folders and environments works in big infrastructure as well. But you have to have some kind of rules, patterns and structure on how to write terraform, so it follows one way across all your engineers.

* Example decide on naming conventions.
* Decide that xx amount of terraform will be built in modules, rather than just random .tf files.
* Decide how you will execute it.
* Manual execution: This approach is not really a good idea as that means an engineer somewhere is doing a terraform apply from his laptop. But its still something you can do if needed.
* Pipeline: If possible as you asked building some kind of CI/CD pipeline that does a terraform init,plan, before terraform apply --auto-approve, so you know what the changes are before being approved, that will help you go back and see on a specific deployment what the terraform plan outputted and have some monitoring over it(also that will allow a few reviews and approvals from other engineers). Also, that means things can be scheduled as well. Terraform works great with Azure DevOps, GitLab and GitHub actions, from what I have worked with.

5. To talk about legacy infrastructure. You have to decide is it worth managing a specific infrastructure that was created manually, with Terraform. What I mean is that if after a few months you will migrate that legacy infra and working on importing the legacy infra to terraform will take you a lot of time, by all means, it's not worth it. Before writing terraform, you need to sit down and plan everything: The good, the bad and the not worth it in the long run.
6. Make code reviews for Terraform, the same way you would for code.

Going back to point number 1, read the book. Its 600 pages with 70% of it are examples. Go through the repo that I shared and see some example structure, even though that's small, believe me if you split it by env and modules, for example, those 4 points you gave at the top: Cloudfront, API, EC2, Lambdas, if you put them in separate modules folders all under modules, that would be much clearer. It's a small start, but it has to start from somewhere. You cannot import 5 years of infra at once. Take it piece by piece. Also, that's how I would deploy it as well. Deploy a VPC, then deploy on top an EC2, and so on, if you get my point.
> 2 votes

# Answer
I usually break companies' terraform into several repositories.

1. terraform-accounts - This is used to create and harden AWS accounts using aws orgs.
2. terraform-networking - This is used to provision company networking. Not only the VPC's but connections to/from AWS.
3. terraform-infra - General shared infrastructure like buckets for big data or SCM or w/e. This stuff is usually owned by the platforms/infa/IT team.

Once the above is taken care of then the rest depends on how the people are organized for that company. So if it's based on applications then I create a repository for every application, but usually, it's based on teams. So I create a repository for every team.
> 0 votes

---
Tags: terraform, terraform-module
---


# Question
Title: Moving a file (with encrypted token) after building a docker on Jenkins
I have a project with NextJS and I build it using Jenkins. I run my app inside a docker container, and pull my code from Github.

In my local project, I have a git-ignored file named `.sentrylirc` that includes my authentication token to Sentry (3rd party monitoring library), which I need to move to the root of my project.

How can I move this file inside my docker container before my build? Where should I store it?

# Answer
> 1 votes
You shouldn't bake these kinds of credentials into the docker container. Instead, you should use some kinda secret storage to hold the secret and load it before you start the application.

Basically, when the docker container starts, whatever started the container should securely retrieve the credentials and set it as an environment variable or the container should fetch the secret.

---
Tags: docker, jenkins
---


title: TerraForm separate stages

text:
# Question
Title: TerraForm separate stages
I want to separate my development stages in the TerraForm repository.

The TerraForm workspaces page states:

*"Workspaces alone are not a suitable tool for system decomposition, because each subsystem should have its own separate configuration and backend, and will thus have its own distinct set of workspaces."*

However, many tutorials, like this one state:

*"There are two primary methods to separate state between environments: (...) and **workspaces**."*

Those two statements seem to be in contradiction. Could someone explain what the best practice is for stage separation? Currently I plan to use separate directories:

```
├── prod
│   ├── main.tf (referencing the modules)
│   ├── variables.tf
│   ├── terraform.tfstate
│   └── terraform.tfvars
├── dev
│   ├── main.tf (referencing the modules)
│   ├── variables.tf
│   ├── terraform.tfstate
│   └── terraform.tfvars
└── modules
   ├── module A
   └── module B

```

# Answer
I don't think there are any best practices because it would depend on both your company structure as well as how your developers manage their code in SCM (gitflow, trunk, etc).

Lets start with the statements that seem to be in contradiction. I think quoted like that they do seem to tell a different story. But lets look at the start of the paragraph where the first quote came from.

> When Terraform is used to manage larger systems, teams should use multiple separate Terraform configurations that correspond with suitable architectural boundaries within the system so that different components can be managed separately and, if appropriate, by distinct teams.

So it's saying that when you have multiple teams using the same terraform directory (aka configuration) then...

> Workspaces alone are not a suitable tool for system decomposition, because each subsystem should have its own separate configuration and backend, and will thus have its own distinct set of workspaces.

Which makes sense. Each team will need different things from their workspace and since all the teams will be sharing workspaces then it kinda falls apart. So in conclusion, different directories and workspaces can be used to separate environments in Terraform but they have certain limitations. In the tutorial you linked, I think it's explained even better:

> To separate environments with potential configuration differences, use a directory structure. Use workspaces for environments that do not greatly deviate from one another, to avoid duplicating your configurations.

The second part of your question about recommendations can get somewhat complicated depending on what level of CICD and automation your company currently has. If your infra is small and the number of changes every month is pretty minimal then it's probably fine to just checkout the code, make the change and deploy it locally.

But if you are a large organization with 100's of changes a week, then you are probably going to want to automate the deployments. A common way of doing that is to trigger CICD on new PR's or changes to certain branches. From there you can have your CICD engine change workspaces based on the branch name. Or more commonly for older companies who used Terraform before workspaces existed, you can just set the state path to something like `${env}/tf.state` because that really has the same effect as just using workspaces.

I'm a Terraform and terratest contribtutor. I'm also the author of cf2tf and the terraform-module-template.
> 1 votes

---
Tags: terraform, terraform-module, terraform-workspace
---


title: Understanding Jenkins plugins and agent

text:
# Question
Title: Understanding Jenkins plugins and agent
I was trying to understand jenkins agents. This page asks to first create jenkins docker agent. But it doesnt say where to execute these steps?

**Q1.** Should we be executing these steps on node or a machine which we want to designate as agent?

The next step asks to setup an agent through Jenkins UI:

**Q2.** Above is nothing but the Jenkins controller UI right?

But above UI does not seem to accept IP address of the agent node on which we staarted docker agent.

**Q3.** Does Jenkins controller automatically discovers running agents reachable on the network?

**Q4.** What are exactly Jenkins plugins in relation with agents? Jenkin glossary defines plugin as "an extension to Jenkins functionality provided separately from Jenkins Core." But that does not explain much of its nature or functionality. This page also explain plugin installation and management on the controller, but doesnt explain exact nature of their functionality.

**Q4.1.** Do plugins run jobs of agent nodes? For example, does Android Emulator plugin installed on controller installs and runs android emulator on available agent?

**Q4.2.** If yes is the answer to Q4.1, does every plugin need corresponding process to be installed on the agent so that agent can carry out functionality specified in the pluin on the controller?

PS: Am a noob in Jenkins and overall DevOps stuff and just trying to wrap my head around Jenkins

# Answer
> Q1. Should we be executing these steps on node or a machine which we want to designate as agent?

You can execute them where ever you want. If you want the agent to run on your local machine, then run it locally. If you want the agent to run on the same hardware as the Jenkins Controller then run the docker command on the Jenkins machine. If you want to run it on a cloud or in a Kubernetes pod, then run the command their.

> Q2. Above is nothing but the Jenkins controller UI right?

Yes

> But above UI does not seem to accept IP address of the agent node on which we staarted docker agent.

It has a `Host` field. Put the IP address or hostname into it.

> Q3. Does Jenkins controller automatically discovers running agents reachable on the network?

No, that is what the above controller UI page is for. You are telling Jenkins, this is how to connect to an agent.

> Q4, Q4.1, Q4.2

These should really be a new question but I will give you a brief explanation.

Agents and plugins are not really related. Plugins are installed on the Jenkins controller and will run where you run your job/pipeline. So this could be on the controller or on an Agent. Also plugins can help you setup agents, like the Amazon Ec2 plugin.

Jenkins can be tough to learn but it is the most powerful CICD engine that exists as long as you use scripted pipelines. Another place that might be helpful is https://community.jenkins.io/
> 0 votes

---
Tags: jenkins, jenkins-pipeline, jenkins-plugins
---


# Question
Title: Setup Folder When Setting up Kubernetes Storage
I am trying to setup automation around my Kubernetes storage and hitting some problems. I thought I would ask if there is a solution for this in the community.

The two Kubernetes storage options I am seeing each have a limitation:

**Dynamic Storage:** You can't control the name of the Persistent Volume nor the directory that it creates on disk (making it hard to connect to again if needed).

**Static Storage:** You have to manually make the folder structure that the Persistent Volume expects.

Both of these can be overcome with more work. But I find it hard to believe that I am the first person with this issue, so I thought I would ask:

**Is there a way using dynamic storage (aka Storage Classes) to choose the Persistent Volume name and folder structure that is created (so it can be re-connected to)?**

OR

**Is there a way to have a manually created Persistent Volume create the needed folder structure given in the yaml?** (This is perferred.)

# Answer
> You can't control the name of the Persistent Volume nor the directory that it creates on disk (making it hard to connect to again if needed).

I'm not entirely sure what you mean here. When you use a PersistentVolumeClaim to request a volume from Kubernetes, you specify the name of the claim. You don't directly specify the name of the `PersistentVolume` that will be created by the `PersistentVolumeClaim`, but that's okay: you mount the volume via the claim.

That is, if I have:

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pgsql-data
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 80Gi

```

Then I can mount this in a pod like this:

```
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: postgres
    image: docker.io/postgres:14
  volumes:
    - name: psql-data
      persistentVolumeClaim:
        claimName: psql-data

```

Kubernetes doesn't care about the folder structure on the volume; once the volume is mounted, your application can create whatever folder structure it wants.
> 0 votes

---
Tags: kubernetes
---


# Question
Title: Gitlab (self hosted gitlab) pipeline fail when trying to fetch repository
I've setup own gitlab server on AWS EC2 Instance based on this image - https://aws.amazon.com/marketplace/pp/prodview-w6ykryurkesjq?ref\_=aws-mp-console-subscription-detail and assign Elastic IP for this instance.

I've prepared some pipeline for repository and getting error (after push and check pipeline status):

```
Running with gitlab-runner 14.3.2 (e0218c92)
  on [PRIVATE IP ADDRESS] JA-qzGJG
Preparing the "docker" executor
Using Docker executor with image node:latest ...
Pulling docker image node:latest ...
Using docker image sha256:c4fbd63932640bbb14c76f80c5b53daf8f01cc1f011d260d07f35bb6874c0c30 for node:latest with digest node@sha256:fec9ab31c9d46ad952abed8119b71e01e995975bd7b580f07b249e803d306dbe ...
Preparing environment
00:02
Running on [RUNNER_NAME] via [PRIVATE IP ADDRESS]...
Getting source from Git repository
02:11
Fetching changes with git depth set to 50...
Reinitialized existing Git repository in /builds/logifiles/queue/.git/
fatal: unable to access 'http://ec2-[OLD_EC2_INSTANCE_IP_ADDRESS].compute-1.amazonaws.com/logifiles/queue.git/': Failed to connect to ec2-[OLD_EC2_INSTANCE_IP_ADDRESS].compute-1.amazonaws.com port 80 after 129988 ms: Operation timed out
ERROR: Job failed: exit code 1

```

I remove IP addreses, due security reasons. My pipelines for repository:

```
image: node:latest
cache:
  paths:
    - node_modules/
stages:
  - dist
before_script:
  - npm i
dist:
  stage: dist
  script:
    - echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
    - npm publish
  rules:
    - if: $CI_COMMIT_BRANCH == "master"

```

So how should i properly handle it ? How to change IP address in pipeline or set different url for gitlab, or maybe prepare some redirect from old ec2 instance domain to new one (from Elastic IP). Is there any other way how can i handle it ?

### Edit 1

This is security group for inbound rules for ec2 instance:

# Answer
A few things here...

1. Removing an IP address has nothing to do with security. Every hacker tool on the planet will happily enumerate IPs whether or not you give them out. So, you can leave the IP there and do the right thing security wise.
2. So, per the above, host everything with https:// and proper user-name/password/api token/etc auth.
3. Allowing "all of internet" inbound is a bad idea in most cases.
4. If the main thing talking to your instance is another EC2, you can have a security group for each EC2 and you an reference one security group in the other one (rather than a specific IP). This is safer and lets you forget about the IP addresses themselves as the security group linking will still work fine even if the IPs change.
> 0 votes

---
Tags: amazon-web-services, gitlab, amazon-ec2, gitlab-ci-runner
---


# Question
Title: Can I change a docker container from a self-delete policy to auto-restart?
I've got a container started (not my code, not my container, but I often manage the server and deal with the aftermath of it being patched) and I need to make a hot-fix to the deployment strategy, I had gone through the steps to change it to auto-restart, but a coworker noticed that the container was started with `--rm`. My guess is that this is circumventing any attempt to start it up after reboots (because the container just isn't there any more)

So is there a way to remove the `--rm` policy from a running container?

# Answer
You can use a docker update. (https://docs.docker.com/engine/reference/commandline/update/).

`docker update --restart always <containerID>/<containerName>`.

Not sure about removing the --rm flag, though
> 0 votes

---
Tags: docker
---


# Question
Title: Kubernetes deployment with multiple containers
I have two containers, `worker` and `dispatcher`. I want to be able to deploy N copies of `worker` and 1 copy of `dispatcher` to the cluster. Is there a deployment that will make this work?

`dispatcher` needs to be able to know about and talk to all of the `worker` instances (`worker` is running a web server). However, the external world only needs to talk to `dispatcher`.

As a stretch goal, I'd like to be able to scale N up and down based on demand.

Questions:

1. Should I be using a Deployment or a StatefulSet? or something else?
2. Do I actually need multiple deployments? Can containers from multiple deployments talk to each other?
3. How do I dynamically scale this?

It seems like I can get partway there with a single Deployment:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      deploy: myapp
  template:
    metadata:
      labels:
        deploy: myapp
    spec:
      containers:
        - name: worker
          image: localhost/worker:latest

```

I expect this will give me 3 workers, but 0 dispatchers. However, if I add `dispatcher` to the `containers` list, I would expect to get 3 of those too, which is not what I want.

# Answer
> 2 votes
> I have two containers, worker and dispatcher. I want to be able to deploy N copies of worker and 1 copy of dispatcher to the cluster. Is there a deployment that will make this work?

Both a Deployment or Statefulset will work.

> dispatcher needs to be able to know about and talk to all of the worker instances (worker is running a web server).

This has to do with Kubernetes Networking plugins and will depend on which plugin your cluster was configured with. Most clusters I have used by default allow traffic across the entire cluster.

> However, the external world only needs to talk to dispatcher.

The main ways to do this would be a Service or an Ingress both are explained here.

> I'd like to be able to scale N up and down based on demand.

https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

> Should I be using a Deployment or a StatefulSet? or something else?

Does your container have state? If so then use a stateful set. The Kubernetes page explains why to use a statefulset https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

> Do I actually need multiple deployments? Can containers from multiple deployments talk to each other?

These things are not really related. You would use multiple deployments so you can configure multiple workloads differently.

---
Tags: kubernetes
---


# Question
Title: Transferred 0 file(s) while transferring war file from Jenkins server to remote server
There's a jenkins server where my jenkinswar.war file is present in `/var/lib/jenkins/workspace/project2/target/jenkinswar.war`

I want this file to be transferred to other remote server at `/opt/docker` location.

So I have configured as below:

Even though the build is successful, still the files transferred are 0.

# Answer
You can try to add an archive stage before this, maybe it isn't picking it because the war file isn't present when it needs to copy... you can also try using '\*/target/\**/jenkinswar.war' for your source file
> 0 votes

---
Tags: jenkins, amazon-web-services, jenkins-pipeline, ssh
---


title: Setting up gitlab phpstan pipeline

text:
# Question
Title: Setting up gitlab phpstan pipeline
I have tried to start using phpstan pipeline on gitlab according to this guide.

The problem is that the pipeline does not work at all (Command 'sh' is not defined) and i don't know how to fix it.

Here is my .gitlab-ci.yml file:

```
stages:
  - check

phpstan:
  stage: check
  image: ghcr.io/phpstan/phpstan
  script:
    - analyse --no-progress --error-format gitlab > phpstan.json

```

And here is the pipeline output:

```
Running with gitlab-runner 15.2.0~beta.17.g34ae4a68 (34ae4a68)
  on blue-5.shared.runners-manager.gitlab.com/default -AzERasQ
Preparing the "docker+machine" executor
Using Docker executor with image ghcr.io/phpstan/phpstan ...
Pulling docker image ghcr.io/phpstan/phpstan ...
Using docker image sha256:797d91431d4ecb9c7c570d793db215dec2ae01f942b85e4e6e7cf4e07d07c8f2 for     ghcr.io/phpstan/phpstan with digest     ghcr.io/phpstan/phpstan@sha256:ac693ee977b314976226205631cd9071364f6c84b3b113f0c9404f9d4747a0b5     ...
Preparing environment
00:01
Running on runner--azerasq-project-37231833-concurrent-0 via runner-azerasq-shared-1658326011-    484bb33b...
Getting source from Git repository
00:03
$ eval "$CI_PRE_CLONE_SCRIPT"
Fetching changes with git depth set to 20...
Initialized empty Git repository in /builds/balikobot/BalikobotAdmin/.git/
Created fresh repository.
Checking out e4512b17 as feature/ci-pipeline...
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:01
Using docker image sha256:797d91431d4ecb9c7c570d793db215dec2ae01f942b85e4e6e7cf4e07d07c8f2 for     ghcr.io/phpstan/phpstan with digest     ghcr.io/phpstan/phpstan@sha256:ac693ee977b314976226205631cd9071364f6c84b3b113f0c9404f9d4747a0b5     ...

  Command "sh" is not defined.

Cleaning up project directory and file based variables
00:01
ERROR: Job failed: exit code 1

```

# Answer
The problem is that an official Docker image of phpstan uses ENTRYPOINT \["phpstan"\] and the Gitlab runner call the image with "sh -c" command. You can override the default entry point (https://docs.gitlab.com/ee/ci/docker/using\_docker\_images.html#overriding-the-entrypoint-of-an-image):

```
phpstan:
  stage: check
  image:
    name: ghcr.io/phpstan/phpstan
    entrypoint: [""]
  script:
    - phpstan analyse

```

I recommend to use a Docker image for phpstan with concrete version (don't use latest tag).
> 3 votes

---
Tags: continuous-integration, gitlab, pipeline
---


# Question
Title: In Ubuntu, how do I change the home path of Jenkins using the CLI?
In the Jenkins web interface, under *Home directory* (Dashboard -\> Mange Jenkins -\> Configure System), the help section says the following:

* "By default, Jenkins stores all of its data in this directory on the file system", referring to /var/lib/jenkins
* "Edit the JENKINS\_HOME variable in your Jenkins configuration file (e.g. /etc/sysconfig/jenkins on Red Hat Linux)"

However, my etc directory doesn't have a directory called sysconfig.

Running the following command returns a lot of files among which only the following seems relevant:

```
find ~/ -type f -name "config.xml"
<...>
/var/lib/jenkins/config.xml
<...>

```

The file contains the following field:

```
<workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULL_NAME}</workspaceDir>

```

Is this the correct field to edit? If so, which syntax should I follow while entering the desired path?

# Answer
> 1 votes
This question was already asked and answered on Stack Overflow. I'll copy the top answer here, but there are several other answers over there that you may find useful:

> For me on Jenkins 2.7.2 on RHEL 7.2 after already starting jenkins and configuring a build, I needed to:
>
> 1. Change the jenkins user's home directory
>
> ```
> sudo su -
> service jenkins stop
> vi /etc/passwd
> #  change the /var/lib/jenkins to /home/jenkins or whatever
>
> ```
> 2. Change the setting in the start script to also find it
>
> ```
> vi /etc/sysconfig/jenkins
> #   change the JENKINS_HOME to /home/jenkins or what ever
>
> ```
> 3. Copy all the data to the new location (eg: /home/jenkins)
>
> ```
> cd /home
> cp -Rf /var/lib/jenkins .
> chown -R jenkins:jenkins *
>
> ```
> 4. Start it back up
>
> ```
> service jenkins start
>
> ```
>
> And that seems to have done it for me.

# Answer
> 1 votes
I was having the same problem on a Centos 7.9 system using Jenkins 2.346.2

Sometime around 2.332.1 Jenkins migrated from init.d to system.d, so the previous method of updating the /etc/sysconfig/jenkins (or /etc/default/jenkins) became deprecated.

You now use overrides through: systemctl edit jenkins

Jenkins systemd reference: https://www.jenkins.io/doc/book/system-administration/systemd-services/

# Answer
> 0 votes
The following script can be used to do what you want:

```
# become root
sudo -i

# stop the jenkins service
systemctl stop jenkins

# create the directory where you want jenkins
mkdir -p /[path to your jenkins instance]

vi /etc/sysconfig/jenkins
# change JENKINS_HOME to /[path to your jenkins instance]

vi /etc/passwd
#  change the default /var/lib/jenkins to /[path to your jenkins instance]

mv -R /var/lib/jenkins /[path to your jenkins instance]

# grant ownership of all the files to jenkins
chown -R jenkins:jenkins .[path to your jenkins instance]

# start jenkins
systemctl start jenkins

# if you want jenkins to start upon every reboot
systemctl enable jenkins

```

---
Tags: jenkins, configuration, ubuntu
---


# Question
Title: Reuse block string without processing it on the fly
I have a block of code that work fine at the moment. But reuse that code is a little ugly.

```
pipeline {
    agent any
    stages {
        stage('Stage 1') {
            steps {
                script {
                    withCredentials([
                        gitUsernamePassword(credentialsId: 'jenkins-credentials', gitToolName: 'Default', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')
                    ]) {
                        sh '''#!/bin/bash
                        export GIT_USERNAME=${GIT_USERNAME};
                        export GIT_PASSWORD=${GIT_PASSWORD};
                        export PROYECT_DIRECTORY=${PROYECT_DIRECTORY};
                        export CHECKOUT_POINT=${CHECKOUT_POINT};
                        export GIT_HTTPS_REPO_DEPLOY=${GIT_HTTPS_REPO_DEPLOY};
                        export MARIADB_HOSTNAME=${MARIADB_HOSTNAME};

                        ./scripts/awesome_script.sh
                        '''
                    }
                }
            }
        }
    }
}

```

The problem is when I apply if statements to use diferents scripts bash inside sh() block. The script `./scripts/awesome _script.sh` need that variables exported. Therefore the code looks like this.

```
script {
                    withCredentials([
                        gitUsernamePassword(credentialsId: 'jenkins-credentials', gitToolName: 'Default', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')
                    ]) {
                        sh '''#!/bin/bash
                        export GIT_USERNAME=${GIT_USERNAME};
                        export GIT_PASSWORD=${GIT_PASSWORD};
                        export PROYECT_DIRECTORY=${PROYECT_DIRECTORY};
                        export CHECKOUT_POINT=${CHECKOUT_POINT};
                        export GIT_HTTPS_REPO_DEPLOY=${GIT_HTTPS_REPO_DEPLOY};
                        export MARIADB_HOSTNAME=${MARIADB_HOSTNAME};

                        ./scripts/awesome_script.sh
                        '''
                        if(env.APP_ENV == 'testing'){
                            sh '''#!/bin/bash
                            export GIT_USERNAME=${GIT_USERNAME};
                            export GIT_PASSWORD=${GIT_PASSWORD};
                            export PROYECT_DIRECTORY=${PROYECT_DIRECTORY};
                            export CHECKOUT_POINT=${CHECKOUT_POINT};
                            export GIT_HTTPS_REPO_DEPLOY=${GIT_HTTPS_REPO_DEPLOY};
                            export MARIADB_HOSTNAME=${MARIADB_HOSTNAME};

                            ./scripts/awesome_script_2.sh
                            '''
                        }
                    }
                }

```

**Very ugly, right ? :/ :(**

What I am looking is something similar like to this, but with correct syntax:

```
script {
                    env.STRING_BLOCK_WITHOUT_PROCESSING = '''
                        export GIT_USERNAME=${GIT_USERNAME};
                        export GIT_PASSWORD=${GIT_PASSWORD};
                        export PROYECT_DIRECTORY=${PROYECT_DIRECTORY};
                        export CHECKOUT_POINT=${CHECKOUT_POINT};
                        export GIT_HTTPS_REPO_DEPLOY=${GIT_HTTPS_REPO_DEPLOY};
                        export MARIADB_HOSTNAME=${MARIADB_HOSTNAME};
                    ''';

                    withCredentials([
                        gitUsernamePassword(credentialsId: 'jenkins-credentials', gitToolName: 'Default', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')
                    ]) {
                        sh '''#!/bin/bash
                        ${STRING_BLOCK_WITHOUT_PROCESSING}

                        ./scripts/awesome_script.sh
                        '''
                        if(env.APP_ENV == 'testing'){
                            sh '''#!/bin/bash
                            ${STRING_BLOCK_WITHOUT_PROCESSING}

                            ./scripts/awesome_script_2.sh
                            '''
                        }
                    }
                }

```

Thanks for all help you can give me. \<3

# Answer
> 1 votes
When you have a variable inside of a string that is called a gstring or groovy string.

In Groovy, which is the language used inside of the script block, you have to use a certain style of quotes if you want to render the variables into their values. Also called string interpolation and the documentation for groovy's gstrings is here.

What you need to do is change your `'''` blocks to `"""`. Because string interpolation only works with `"` quotes and not `'` quotes.

Here is a full example of how I would probably write the code:

```
script {

    // This single forward slash makes the first line of the string begin with export and not be empty
    String bashVars = """\
        export GIT_USERNAME=${GIT_USERNAME};
        export GIT_PASSWORD=${GIT_PASSWORD};
        export PROYECT_DIRECTORY=${PROYECT_DIRECTORY};
        export CHECKOUT_POINT=${CHECKOUT_POINT};
        export GIT_HTTPS_REPO_DEPLOY=${GIT_HTTPS_REPO_DEPLOY};
        export MARIADB_HOSTNAME=${MARIADB_HOSTNAME};
    """

    withCredentials([
        gitUsernamePassword(credentialsId: 'jenkins-credentials', gitToolName: 'Default', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')
    ]) {

        // Groovy ternary operator aka one line if statement
        String scriptPath = env.APP_ENV == 'testing' ? './scripts/awesome_script_2.sh' : './scripts/awesome_script.sh'

        String script = """\
            #!/bin/bash
            ${bashVars}
            ${scriptPath}
        """

        sh(script)
    }
}

```

Notice I used variable typing? It will give you better error messages if something does go wrong in your pipeline.

As you advance and become better with Jenkins you might want to switch to scripted pipelines. They are a lot more powerful than declarative.

EDIT: While my answer is great for anyone wanting to know the specifics about string interpolation in groovy, the answer by @a25bedc5-3d09-41b8-82fb-ea6c353d75ae is really good for someone wanting to have a scripted pipeline with conditional stages based on something like a variable.

# Answer
> 1 votes
The `withCredentials` would be setting the environment variables for you so you wouldn't need to use export as they will already be passed into the shell.

So you can pass in the remaining variables as environment variables and then use `when` to control the flow.

```
pipeline {
    agent any
    stages {

        stage('Stage Testing') {
            when {
                environment name: 'APP_ENV', value: 'testing'
            }
            environment {
                PROYECT_DIRECTORY = '<replace this with testing value>'
                CHECKOUT_POINT    = '<replace this with testing value>'
                GIT_HTTPS_REPO_DEPLOY    = '<replace this with testing value>'
                MARIADB_HOSTNAME    = '<replace this with testing value>'
            }
            steps {
                script {
                    withCredentials([
                        gitUsernamePassword(credentialsId: 'jenkins-credentials', gitToolName: 'Default', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')
                    ]) {
                        sh '''#!/bin/bash
                        ./scripts/awesome_script_2.sh
                        '''
                    }
                }
            }
        }
        stage('Stage Production') {
            when {
                environment name: 'APP_ENV', value: 'production'
            }
            environment {
                PROYECT_DIRECTORY = '<replace this with production value>'
                CHECKOUT_POINT    = '<replace this with production value>'
                GIT_HTTPS_REPO_DEPLOY    = '<replace this with production value>'
                MARIADB_HOSTNAME    = '<replace this with production value>'
            }
            steps {
                script {
                    withCredentials([
                        gitUsernamePassword(credentialsId: 'jenkins-credentials', gitToolName: 'Default', usernameVariable: 'GIT_USERNAME', passwordVariable: 'GIT_PASSWORD')
                    ]) {
                        sh '''#!/bin/bash
                        ./scripts/awesome_script.sh
                        '''
                    }
                }
            }
        }
    }
}

```

You will also want to avoid string interpolation when dealing with credentials as explained here so it is best to use the `''` quotes when handling credentials.

---
Tags: jenkins, jenkins-pipeline, bash, groovy
---


# Question
Title: How to ansible-vault files as they are commited to Git
I'm trying to use ansible-vault to secure the secret files in my project before I push them to Git. There's loads of advice out there on how to set this up in part, but everything I've read is specifically for diff'ing these files, not how to encrypt them as you put them in - it looks like to initially commit them you need to manually vault them first. Is there a way of doing this vaulting on the fly?

What I have so far: .git/config:

```
 [diff "ansible-vault"]
 textconv = "ansible-vault view"

```

ansible.cfg:

```
 [defaults]
 vault_password_file = .vault

```

.gitattributes:

```
key.pem diff=ansible-vault merge=binary

```

This works fine if I run the following commands:

```
 ansible-vault encrypt key.pem
 git add key.pem
 ansible-vault decrypt key.pem
 git diff --cached

```

I'd like to automate the ansible-vault encrypt/decrypt commands within git. Any ideas?

# Answer
I just had the same want for my personal learning experience (home-lab). What I found was the .git/hooks/pre-commit would help. I have not automated the process, so for your inspiration here are the parts I have.

The .git/hooks/pre-commit is a bash script. The FILE\_PATTERN variable determines the files I want to find and warn about are not ansible-vault encrypted. FOr me that would be all yaml files containing variables I don't want to share.

```
#!/bin/sh
#
# Ansible Vault Secrets Git Hook
#
# Hook to check if an un-encrypted FILE_PATTERN file is being commited. Useful if secrets
# are retained in ansible vault encrypted file(s) that should never be committed to the repository
# un-encrypted. Contact a repository owner for the ansible vault password.
#
# Put this file in .git/hooks/pre-commit

# set -o xtrace
set -o nounset

FILE_PATTERN="my_secrets_file.yaml\|vars/"
ENCRYPTED_PATTERN="\$ANSIBLE_VAULT"

is_encrypted() {
  local file=$1
  if ! git show :"$file" | grep --quiet "^${ENCRYPTED_PATTERN}"; then
    echo "Located a staged file that should be encrypted:\n> ${file}\n"
    echo "Please un-stage this file. If you are adding or updating this file, please encrypt it before staging."
    echo "Alternatively, you can git checkout the latest encrypted version of the file before committing.\n"
    echo "Remember... Only YOU Can Prevent Secret Leakage."
    exit 1
  fi
}

echo "Running pre-commit checks..."
git diff --cached --name-only | grep "${FILE_PATTERN}" | while IFS= read -r line; do
  is_encrypted "${line}"
done

```

This solves part 1 - i.e. letting me know that I have secrets about to get committed and stopping the misery right there. A simple "git commit" will get this caught.~

The 2nd part is encrypting the necessary files. This is simply a matter of again finding the relevant files and encrypting these. I have made this script to put some convenience into this. The 'files' variable contains the (same) patterns to look for the files.

```
#!/bin/bash

# If number of arguments is 0
if [ $# -eq 0 ]
  then
    echo "This script will encrypt of decrypt all files containing secrets."
    echo "There are all files in vars as well as all secrets.yaml files under each service."
    echo "Specify 'decrypt' or 'encrypt' as argument"
    echo "If you put the vault password in a password file named .vault_password, the script will not ask for a password."
    exit 1
fi

files=`find . -type f -name "me_secrets_file.yaml"`
files="$files vars/*"

password_type=--ask-vault-password
if [ -f ".vault_password" ]
  then
    if [ `stat -c %a .vault_password` != "600" ]
      then
        echo ".vault_password file has bad permissions; fixing this to 600"
        chmod 600 .vault_password
    fi
    password_type="--vault-password-file .vault_password"
fi

if [ $1 == "encrypt" ]
  then
    ansible-vault encrypt $password_type $files
    for value in $files; do
        echo $value;
    done

elif [ $1 == "decrypt" ]
  then
    ansible-vault decrypt $password_type $files
    for value in $files; do
        echo $value;
    done
else
    echo "Wrong argument supplied.  Run without arguments to see allowed ones."
fi

```

Used as:

```
./vault.sh {encrypt|decrypt}

```

This solves part 2 - encryption/decryption of the necessary files.

I am sure these two parts can be combined so that encryption happens as part of the pre-commit hook on any file which is not already encrypted. Improve by putting -´.vault\_password in ~/.vault\_password and so on.

The pre-commit script is not originally of my doing, but I did not save the reference.
> 5 votes

---
Tags: git, ansible-vault
---


# Question
Title: OpenStack API Access over secondary ethernet connection or NIC
I am trying to configure my server to utilize a secondary NIC card. I want the server to publish API access on both NICs at the same time. See the attached picture for a configuration diagram that shows that each server has two NICs, one configured with Internet access and the other wired to another server through a network switch.

How do I make OpenStack utilize both NICs at the same time?

I've seen the multi-nic feature in OpenStack, but that seems to link OpenStack Networks together, not physical NICs. Another option I've looked into is using the routing tables, but I don't know if this is possible/best practice.

Thanks,

Taylor

# Answer
There are many layers to that question :

* How did you deploy Openstack? This will heavily influence the flexibility you have the expose API access.
* I assume you mean the Openstack API (nova,neutron,keystone,cinder) itself?

Usually, the core API services are listening on your internal networks only.
> 0 votes

---
Tags: networking, openstack
---


title: Cannot start Kubernetes Dashboard

text:
# Question
Title: Cannot start Kubernetes Dashboard
I'm trying to install Kubernetes Cluster with Dashboard on Ubuntu 20.04 TLS using the following commands:

```
swapoff -a

# Remove following line from /etc/fstab
/swap.img       none    swap    sw      0       0

sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker

sudo apt install apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" >> ~/kubernetes.list
sudo mv ~/kubernetes.list /etc/apt/sources.list.d
sudo apt update
sudo apt install kubeadm kubelet kubectl kubernetes-cni

sudo kubeadm init --pod-network-cidr=192.168.0.0/16

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

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

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml

kubectl proxy --address 192.168.1.133 --accept-hosts '.*'

```

But when I open `http://192.168.1.133:8001/api/v1/namespaces/default/services/https:kubernetes-dashboard:https/proxy`

I get:

```
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "services \"kubernetes-dashboard\" not found",
  "reason": "NotFound",
  "details": {
    "name": "kubernetes-dashboard",
    "kind": "services"
  },
  "code": 404
}

```

I tried to list the pods:

```
root@ubuntukubernetis1:~# kubectl get pods --all-namespaces
NAMESPACE              NAME                                         READY   STATUS              RESTARTS       AGE
kube-flannel           kube-flannel-ds-f6bwx                        0/1     Error               11 (29s ago)   76m
kube-system            coredns-6d4b75cb6d-rk4kq                     0/1     ContainerCreating   0              77m
kube-system            coredns-6d4b75cb6d-vkpcm                     0/1     ContainerCreating   0              77m
kube-system            etcd-ubuntukubernetis1                       1/1     Running             1 (52s ago)    77m
kube-system            kube-apiserver-ubuntukubernetis1             1/1     Running             1 (52s ago)    77m
kube-system            kube-controller-manager-ubuntukubernetis1    1/1     Running             1 (52s ago)    77m
kube-system            kube-proxy-n6ldq                             1/1     Running             1 (52s ago)    77m
kube-system            kube-scheduler-ubuntukubernetis1             1/1     Running             1 (52s ago)    77m
kubernetes-dashboard   dashboard-metrics-scraper-7bfdf779ff-sdnc8   0/1     Pending             0              75m
kubernetes-dashboard   dashboard-metrics-scraper-8c47d4b5d-2sxrb    0/1     Pending             0              59m
kubernetes-dashboard   kubernetes-dashboard-5676d8b865-fws4j        0/1     Pending             0              59m
kubernetes-dashboard   kubernetes-dashboard-6cdd697d84-nmpv2        0/1     Pending             0              75m
root@ubuntukubernetis1:~#

```

Checking kube-flannel pod logs:

```
kubectl logs -n kube-flannel kube-flannel-ds-f6bwx -p
Defaulted container "kube-flannel" out of: kube-flannel, install-cni-plugin (init), install-cni (init)
I0724 14:49:57.782499       1 main.go:207] CLI flags config: {etcdEndpoints:http://127.0.0.1:4001,http://127.0.0.1:2379 etcdPrefix:/coreos.com/network etcdKeyfile: etcdCertfile: etcdCAFile: etcdUsername: etcdPassword: version:false kubeSubnetMgr:true kubeApiUrl: kubeAnnotationPrefix:flannel.alpha.coreos.com kubeConfigFile: iface:[] ifaceRegex:[] ipMasq:true ifaceCanReach: subnetFile:/run/flannel/subnet.env publicIP: publicIPv6: subnetLeaseRenewMargin:60 healthzIP:0.0.0.0 healthzPort:0 iptablesResyncSeconds:5 iptablesForwardRules:true netConfPath:/etc/kube-flannel/net-conf.json setNodeNetworkUnavailable:true}
W0724 14:49:57.782676       1 client_config.go:614] Neither --kubeconfig nor --master was specified.  Using the inClusterConfig.  This might not work.
E0724 14:49:57.892230       1 main.go:224] Failed to create SubnetManager: error retrieving pod spec for 'kube-flannel/kube-flannel-ds-f6bwx': pods "kube-flannel-ds-f6bwx" is forbidden: User "system:serviceaccount:kube-flannel:flannel" cannot get resource "pods" in API group "" in the namespace "kube-flannel"

```

Do you know how I can fix the issue?

# Answer
> 3 votes
The URL you're querying (http://192.168.1.133:8001/api/v1/namespaces/default/services/https:kubernetes-dashboard:https/proxy ) is wrong.

According to the last yaml file you applied (https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml ), and as we could guess from your `kubectl get pods -A`: the kubernetes-dashboard Service is located in the kubernetes-dashboard namespace. Not the default namespace.

Although if you just want to connect kubernetes dashboard: instead of the `kubectl proxy` command you run, I would go with `kubectl port-forward -n kubernetes-dashboard deploy/kubernetes-dashboard 8443:8443`, then open my browser to `https://localhost:8443`

---

Then, there's the case of your SDN. In your `kubectl get pods`, we can see the kube-flannel pod, in kube-flannel namespace, is in `Error`.

Look at the logs for this container, and try to figure out why it does not start (`kubectl logs -n kube-flannel kube-flannel-ds-xxxx -p`).

It's been years I didn't setup flannel, although I remember that in addition to applying their RBAC & daemonsets yamls, I also had to patch nodes, allocating them with a CIDR. Eg: `kubectl patch node my-node-1 -p '{ "spec": { "podCIDR": "10.32.3.0/24" } }' --type merge` (each podCIDR must be unique, each node would have its own range hosting Pods. If I'm not mistaken, each podCIDR must be a subset of flannel's net-conf.json Network subnet -- look at the ConfigMap created while installing flannel).

And as of your last comment: the error tells us the following

```
Failed to create SubnetManager: error retrieving pod spec for 'kube-flannel/kube-flannel-ds-f6bwx': pods "kube-flannel-ds-f6bwx" is forbidden: User "system:serviceaccount:kube-flannel:flannel" cannot get resource "pods" in API group "" in the namespace "kube-flannel"

```

Looking back at the files you've used setting up flannel, you mentioned that one, that setups workloads in the kube-flannel namespace, then this rbac one, creating a clusterrolebinding for a serviceaccount in kube-system. To fix your SDN, you may want to create the following:

```
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel-fix
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
  - kind: ServiceAccount
    name: flannel
    namespace: kube-flannel

```

And for the record: the kube-flannel-rbac is not necessary in your case. It would be, had you installed flannel from their legacy manifest (https://github.com/flannel-io/flannel/blob/master/Documentation/k8s-manifests/kube-flannel-legacy.yml). In your case, that ClusterRoleBinding we're fixing should have been created properly, only applying https://github.com/flannel-io/flannel/blob/master/Documentation/kube-flannel.yml

---
Tags: kubernetes
---


title: Limit and request decleration

text:
# Question
Title: Limit and request decleration
it's needed to add `"" OR ''` to the request/limit configurations? For example:

```
  resources:
    limits:
      cpu: 100m
      memory: 300Mi
    requests:
      cpu: 1m
      memory: 50Mi

```

vs.

```
  resources:
    limits:
      cpu: "100m"
      memory: "300Mi"
    requests:
      cpu: "1m"
      memory: "50Mi"

```

# Answer
It is not. In the case you mention.

The only reason you will have to add quotes surrounding values is when there's room for confusion, converting your YAML into a JSON.

In your sample, you probably noticed that both versions work. Not setting any quotes doesn't end up with an error.

However, the following would be invalid:

```
  resources:
    limits:
      cpu: 1
      memory: 300Mi

```

If you try to create a workload with a resource limits such as above, you would get an error: object is invalid. To fix it, you will have to quote your cpu limit, such as:

```
  resources:
    limits:
      cpu: "1"
      memory: 300Mi

```

This has to do with your client, converting this yaml into a JSON before posting to the API. A JSON that says `"resource": { "limits": { "cpu": 1 } }` is valid on paper. Although from the server perspective, you're using an integer, when a string is expected (as per podSpec / resources schema).

So: no, it is not needed to have `""` or `''` surrounding resource requests or limits, most of the time. Until your requested value can be casted as an integer.
> 0 votes

---
Tags: kubernetes
---


# Question
Title: What permission is required to deploy release?
What permission is required to allow a user to manually deploy (or redeploy) a stage in an Azure DevOps Release Pipeline?

# Answer
Found it!

The permissions are set on each release pipeline itself:

"Manage Deployments" allows users to come in and deploy to their environment without allowing them to edit the pipeline.
> 1 votes

---
Tags: continuous-deployment, azure-pipelines, release
---


# Question
Title: NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized
We have a cluster with 4 worker nodes and 1 master, and the flannel CNI installed. 1 kube-flannel-ds-xxxx pod running on every node.

They used to run fine, but 1 node suddenly entered NotReady state and does not come out of it anymore.

journalctl -u kubelet -f on the node constanly emits "cni plugin not initialized"

```
Jul 25 14:44:05 ubdock09 kubelet[13076]: E0725 14:44:05.916280   13076 kubelet.go:2349] "Container runtime network not ready" networkReady="NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized"

```

Deleting the flannel pod makes a new one start up but the pluin keeps being uninitialized. What can we do or check to fix this?

# Answer
> 6 votes
Found the cause in journalctl of containerd.

```
Jul 25 15:10:36 ubdock09 containerd[23164]: time="2022-07-25T15:10:36.480398235+02:00" level=error msg="failed to reload cni configuration after receiving fs change event(\"/etc/cni/net.d/.10-flannel.conf.swp\": REMOVE)" error="cni config load failed: failed to load CNI config file /etc/cni/net.d/10-flannel.conf: error parsing configuration: missing 'type': invalid cni config: failed to load cni config"

```

The Ready machines did not have /etc/cni/net.d/10-flannel.conf so I just removed the /etc/cni/net.d directory and the network device cni0 that was created by the container network interface.

```
id@machine:/# ip -4 addr show
6: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 10.244.11.1/24 brd 10.244.11.255 scope global cni0
       valid_lft forever preferred_lft forever

ip link delete cni0

```

Then restarted containerd and the flannel pod. Now the node is ready and cni0 is recreated.

---
Tags: docker, kubernetes
---


# Question
Title: Connection Refused to Unix socket in Docker container from host
I have a service running in Docker that listens on a Unix Domain Socket, and a client running on the Docker host (a Mac). The client gets a "Connection Refused" error trying to connect.

I'm mapping the volume when I run the server (docker run -it -v /localpath:/var/run myservice) and I see the socket file created in the local dir just fine.

It works fine if I also run the client in Docker (different container instance), or if I run both locally. But if I run one side in Docker and the other locally it fails (I've tried both directions). I thought it might be a uid/gid mismatch but that looks ok, and if I force them to be different I get a permission denied error.

My app is using Java 16's UnixDomainSocketAddress, but I've also tested with a python script (using an AF\_UNIX socket) and see the same problem, so it seems like a Docker thing. Any ideas?

# Answer
> 2 votes
Sharing (mounting?) Unix sockets between the macos host and the linux vm in which docker containers are run is not possible at this time. Work on this issue has stopped.

https://github.com/docker/for-mac/issues/483

* The linked github issue describes a ssh agent specific workaround that is part of docker now.
* Other programs are also designed to work over a network as well (like X11 or pulseaudio). Docker containers can see their host at `host.docker.internal` on docker desktop for mac and windows. I dont know what it is for docker on linux. https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host
* The previous technique can be augmented for other programs that are adamant about using sockets. You can use `socat` on the host to map a socket on the host to a port on the host. Then use `socat` inside the container to map the host's port to a socket within the container. However this introduces another process you have to manage. You might need
    + some clever scripting inside the container to run ur program and socat
    + an init system / process manager inside the container
    + or theoretically, u could run socat in its own container, then share the socket between your app's container and socat's container. ive never tried this tho

---
Tags: docker
---


# Question
Title: Cloudformation template with EC2 using docker compose
I'm relatively new to Cloudformation, and had a few questions about my template and best practices. I'm facing a few hurdles, and there is a lot of information out there, it's a bit overwhelming, so any feedback would be highly appreciated. I'm not looking for detailed code etc. just some good insights on how I can improve my steps.

I'm trying to set up a basic Node/Express API:

* On push to Git repo
    + Build Docker image and push to private AWS ECR repo
    + After successful push, deploy Cloudformation template that provisions
        - An EC2 + security group with Elastic IP assigned
        - Run docker compose in Userdata of EC2 to get app up and running

This is my UserData (I do need some specific help here!)

```
UserData: !Base64 |
        #!/bin/bash -ex
        yum update -y
        yum install docker -y
        service docker start
        usermod -a -G docker ec2-user
        echo "Start Docker service"
        apt-get update
        apt-get install docker-compose-plugin
        apt install amazon-ecr-credential-helper
        echo "APT-GET update complete"
        echo "{ \"credHelpers\": { \"<my_acc_id>.dkr.ecr.<my_region>.amazonaws.com\": \"ecr-login\" } }" > ~/.docker/config.json
        systemctl restart docker
        echo "
        version: "3.9"
        services:
          my-app:
            image: <acc_id>.dkr.ecr.<my_region>.amazonaws.com/my-repo
            environment:
              STAGE: staging
              VIRTUAL_HOST: my-customdomain.com
              VIRTUAL_PORT: 3000
            ports:
              - "3000:3000"
            restart: always
            networks:
              - my-network

          https-portal:
            image: steveltn/https-portal:1
            ports:
              - '80:80'
              - '443:443'
            links:
              - my-app
            environment:
              STAGE: production
            volumes:
              - /var/run/docker.sock:/var/run/docker.sock:ro
            networks:
              - my-network

        volumes:
          https-portal-data:
        networks:
          my-network:
            driver: bridge
        " > docker-compose.yaml
        docker compose up -d

```

Status: Cloudformation template deploys successfully, all resources set up. But the Userdata doesn't run, so my EC2 never sets up my app.

Issues / Questions:

* The Userdata never ran, I can't find see any of the above echo statements in the logs `/var/log/cloud-init.log`. When I SSH into the instance I can't find any of these files. How do I debug this better?
* Is there a better way to get the docker-compose data in there? writing the whole file in the UserData script seems inefficient. Is there a better way to do this?
* On code update, Cloudformation stack is updated, this does not run Userdata(?) (I know it only runs when an instance is first created, but I would like some confirmation that Cloudformation update does not trigger this.
* What is the best practice here if I want to re-run docker compose in my Ec2 after every Cloudformation deploy? If it does trigger Userdata, what could be wrong here?
* Is this an ideal flow? Are there any improvements I can make here, considering I'm not an expert, but willing to spend some time learning where required.

I appreciate anyone taking the time to answer these questions. Thanks!

# Answer
So I found some answers over time, posting them here in case it helps anyone.

* The Userdata never ran, I can't find see any of the above echo statements in the logs /var/log/cloud-init.log. When I SSH into the instance I can't find any of these files. How do I debug this better?

ANS: There was an error in my Userdata, I SSHed into the instance and ran the script manually to debug and fix all issues.
* On code update, Cloudformation stack is updated, this does not run Userdata(?) (I know it only runs when an instance is first created, but I would like some confirmation that Cloudformation update does not trigger this

ANS: Cloudformation terminates the old instance and spins up a new one on each deploy, this causes the Userdata to be run each time.
* Is this an ideal flow? Are there any improvements I can make here, considering I'm not an expert, but willing to spend some time learning where required.

ANS: It was not. The primary reason I was doing this was to fire async requests from one lambda to another, without waiting for the results. This is not possible, as the lambda will not wait for any requests that you do not `await` meaning you still have to wait for those operations. I tried asynchronous invocation but it still did not work (For those interested I posted a question about it here). So I switched to using SNS to publish messages from one lambda to trigger another, achieving my requirement for fire and forget requests.
> 1 votes

---
Tags: docker, docker-compose, amazon-ec2, aws-cloudformation, aws-ecr
---


# Question
Title: Grafana NGINX reverse proxy not functioning correctly
I seem to be having trouble with Grafana behind an nginx proxy. I'm getting console errors and errors in Grafana, and the changes I try to make in Grafana are not working.

Errors: From within Grafana I get "Origin not allowed" when trying to access the site from https://grafana.domainname.dev and making any action.

I see console errors of

this kind whenenver i load a page: Failed to load resource: the server responded with a status of 4030(forbidden) URL: https://grafana.domainname.dev/public/fonts/roboto/RxZJdnzeo3R5zSexge8UUVtXRa8TVwTICgirnJhmVJw.woff2 Failed to load resource: the server responded with a status of 4030(forbidden) URL: https://grafana.domainname.dev/public/fonts/fontawesome-webfont.ttf?v=4.7.0

this kind whenever i go into submenus or try to make changes (these two errors occur the same time as origin not allowed error) Failed to load resource: the server responded with a status of 4030(forbidden) URL: https://grafana.domainname.dev/api/frontend-metrics

Uncaught (in promise)

```
{
    "status": 403,
    "statusText": "Forbidden",
    "data": {
        "message": "origin not allowed\n",
        "error": "Forbidden",
        "response": "origin not allowed\n"
    },
    "config": {
        "method": "POST",
        "url": "api/frontend-metrics",
        "data": {
            "events": [
                {
                    "name": "frontend_boot_first-paint_time_seconds",
                    "value": 1.045
                },
                {
                    "name": "frontend_boot_first-contentful-paint_time_seconds",
                    "value": 1.045
                },
                {
                    "name": "frontend_boot_load_time_seconds",
                    "value": 1.311
                }
            ]
        },
        "retry": 0,
        "headers": {
            "X-Grafana-Org-Id": 1
        },
        "hideFromInspector": true
    }
}

```

Grafana Config:

General Configuration:

```
instance_name = grafana.domainname.dev

Server block:
[server]
# Protocol (http, https, h2, socket)
;protocol = http

# The ip address to bind to, empty will bind to all interfaces
;http_addr =

# The http port  to use
;http_port = 3000

# The public facing domain name used to access grafana from a browser
domain = grafana.domainname.dev

# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
;enforce_domain = true

# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
root_url = https://grafana.domainname.dev/

# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
;serve_from_sub_path = false

```

Everything else is unaltered, except for mail settings I set further down. When i try to turn on enforce\_domain it ends up in a redirect loop and the browser can't connect.

NGINX Config:

/etc/nginx/sites-available/grafana.domainname.dev :

```
map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {

        root /var/www/grafana/html;
        index index.html index.htm index.nginx-debian.html;

        server_name grafana.domainname.dev www.grafana.domainname.dev;

        location / {
                proxy_pass http://localhost:3000/;
        }

        location /api/live {
          rewrite  ^/(.*)  /$1 break;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection $connection_upgrade;
          proxy_set_header Host $http_host;
          proxy_pass http://localhost:3000/;
        }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/grafana.domainname.dev/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/grafana.domainname.dev/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = grafana.domainname.dev) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

        listen 80;
        listen [::]:80;

        server_name grafana.domainname.dev www.grafana.domainname.dev;
    return 404; # managed by Certbot

}

```

Some of the above was added by certbot, and I didn't touch any of that, and I tried to follow grafana's tutorial as well as some forum suggestions but to no avail!

/etc/nginx/nginx.conf :

```
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {
        map $http_upgrade $connection_upgrade {
         default upgrade;
         '' close;
        }

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

```

This is all standard except I did add the map $http\_upgrade part however that doesn't look to have done anything.

If anyone has any insight here, I'd really appreciate it! It looks like something isn't making it back to localhost:3000 however I'm not sure why/how that is possible when nginx is configured to send everything from grafana.domainname.dev to localhost:3000. Appreciate the help in advance!

# Answer
> 1 votes
The `Host` header needs to be preserved now.

For nginx: `proxy_set_header Host $http_host;` in BOTH your Location blocks.

For Apache2: `ProxyPreserveHost On` \[1\]

\[1\] https://github.com/grafana/grafana/issues/45117#issuecomment-1033842787

---
Tags: monitoring, nginx, grafana
---


# Question
Title: dev/stage/prod in separate AWS accounts, managed via terraform cloud workspaces, how can I use lb ip in DNS records for each env?
We currently have 4 aws accounts:

* root - consolidated billing, domain purchased via route 53
* development
* staging
* production

And they're all managed via terraform cloud as separate workspaces.

in dev/stage/prod I have a load balancer routing requests to ECS and various other resources.

I'd like to use the same domain to point to each environment with the following path:

* dev.mydomain.com =\> development load balancer
* stage.mydomain.com =\> staging load balancer
* mydomain.com =\> prodution load balancer

If they were all in 1 single AWS account/workspace, this would be easy peasy, take the output of that static IP and add it into the route 53 A record for each subdomain.

But, is it possible at all to achieve this across multiple aws accounts, or is there a better pattern to follow to achieve this?

# Answer
> 1 votes
One simple way would be to delegate the subdomain of `mydomain.com` for each account to that account's Route53 service. After you do this, the credentials that allow Terraform to create load balancers, servers, and other things in the Dev account can also create/update/delete the DNS records for `dev.mydomain.com`. The different credentials that manage resources in the Stage account can also manage DNS entries in `stage.mydomain.com`. The DNS for the different accounts is kept separate just like the other resources.

The way to do this is to create `dev.mydomain.com` as a public domain in the Dev account's Route53. Take down the list of DNS servers reported there, and add them as NS records for the name `dev.mydomain.com` in the Root account's Route53. Follow a similar pattern for the subdomains for the other accounts.

# Answer
> 0 votes
How about having all the subdomains pointing to the public endpoint of the load balancer? You can anytime use CNAME record for the pointing.

You can easily modify your terraform code to fetch the endpoint of the load balancer and add/modify the DNS entry.

---
Tags: amazon-web-services, terraform, dns, terraform-workspace
---


# Question
Title: How to expose a service ( Experssjs Api ) deployed on minikube ( 192.168.49.2 ) to be able to access it from another device in the same network?
I've created a service inside minikube (expressjs API) running on my local machine, so when I launch the service using `minikube service wedeliverapi --url` i can access it from my browser with `localhost:port/api`

minikube IP : 192.168.49.2

But I also want to access that service from another device so I can use my API from a flutter mobile application, how can I achieve this goal?

# Answer
> 0 votes
# **TLDR;**

*Look at **`NodePort`** or **`Ingress`** to expose a Kubernetes `minikube` service externally*.

For `minikube` specifically, there is one last networking layer between the `minikube` VM and the host. You need to enable port forwarding from the Host into the VM. To forward the entire default `minikube` `NodePort` range:

```
for port in {30000..32767}; do VBoxManage controlvm minikube natpf1 "NodePort$port,tcp,,$port,,$port"; done

```

To disable the port forwarding when you're done:

```
for port in {30000..32767}; do VBoxManage controlvm minikube natpf1 delete "NodePort$port"; done

```

## Long Answer

The default `Service` type is `ClusterIP`, which only exposes the Service ***inside*** the cluster via a cluster-internal IP.

To expose a `Service` ***outside*** the `minikube` cluster, there are a few options provided by Kubernetes.

First, we can look at `ServiceTypes`:

1. **`NodePort`** \- Exposes a service on each cluster node at a specific port. Cluster networking routes the packets to the target `Service`'s `Pod`s. This is the most basic way to expose a service externally. It has existed for many years in Kubernetes. ***This is probably the simplest way to expose a `Service`* for testing in `minikube`**. However, if you want to do anything fancy such as TLS/SSL termination, load balacning, virtual hosts, or routing rules... use an `Ingress`.
2. `LoadBalancer` \- Exposes a service using a cloud-native Load Balancer. This is for production clusters, and probably not useful for your `minikube` use case. It usually creates a dynamic `NodePort` for use as the cloud Load Balancer's backend target port.
3. `ExternalName` \- A way to use externally hosted services through a cluster DNS `CNAME` record. Maps the service name directly to an outside DNS address, and bypasses the need for endpoint records. *Although it's good to know this exists, this is not very useful for your use case of exposing a cluster service externally*.

Next, we can look at port forwarding:

* `kubectl port-forward` command is a way to forward local traffic into a `Pod` within a Kubernetes cluster. This feature is built into `kubectl`, and is mostly useful for local development and one-off tasks where you need to access a `Pod` directly. This works with `Pod` names, `Deployment`s, and `ReplicaSets`.

```
 kubectl port-forward podname-nnnnn-xxxx $LOCALPORT:$CONTAINERPORT

```

This is probably the simplest method for accessing a `Pod` providing a `Service` quickly in order to test that it's working properly and accepting traffic.

Finally, we can look at `Ingress` and Ingress Controllers (default: `nginx`):

* `Ingress`: An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting. An `Ingress Controller` usually runs inside a `Pod` in the `kube-system` namespace and provides these features which are configurable through the `Ingress` Kubernetes API object.

For `minikube`, you need to enable it as an addon:

```
minikube addons enable ingress

```

Follow the `minikube` `Ingress` tutorial here to get started using `ingress-nginx`.

# Answer
> 0 votes
One easy way is to have proxy for outside your machine, I can not comment due to low reputation. You can use apache or any other like HA, nginx

# Answer
> 0 votes
It heavily depends on minikube's start `--driver` option. I was able to handle it with `--driver=none`, which requested the `cri-docker.service` to be running. Summarizing: Preinstall cri-docker service: e.g. Ubuntu 20:

```
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update -y
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

wget https://github.com/Mirantis/cri-dockerd/releases/download/v${VER}/cri-dockerd-${VER}.amd64.tgz
tar xvf cri-dockerd-${VER}.amd64.tgz
sudo mv cri-dockerd/cri-dockerd /usr/local/bin/
tar xvf cri-dockerd-${VER}.amd64.tgz
sudo mv cri-dockerd/cri-dockerd /usr/bin/
wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
sudo mv cri-docker.socket cri-docker.service /etc/systemd/system/
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl start cri-docker.socket

```
0. run your minikube, e.g. `minikube start --driver=none --container-runtime=docker` , also check `minikube ip`
1. deploy app - run your service
2. expose the service
3. run ingress ( as suggestet above - `minikube addons enable ingress` )
4. you should now be able to access it externally.

PS Many thanks to the post creator: https://stackoverflow.com/a/60726849/6571708

---
Tags: docker, kubernetes, kubectl, minikube
---


# Question
Title: Is there a "tracing" service that comes with Istio?
This page: https://istio.io/latest/docs/tasks/observability/gateways/#option-2-insecure-access-http

Shows how to setup external visibility to the telemetry addons for Istio. One of those is shown to be "tracing". It instructs to create a virtual service like this:

```
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: tracing-vs
  namespace: istio-system
spec:
  hosts:
  - "tracing.${INGRESS_DOMAIN}"
  gateways:
  - tracing-gateway
  http:
  - route:
    - destination:
        host: tracing
        port:
          number: 80

```

This seems to imply that there is a service that can be installed that holds traces. But all I can find is docs on how to integrate with Jaegar, Lightstep and Zipkin. Nothing for a standalone tracing service.

Is there a such a thing? And if so is there any docs on how to install it?

# Answer
> 1 votes
From the documentation:

https://istio.io/latest/docs/reference/config/telemetry/#Tracing https://istio.io/latest/docs/tasks/observability/distributed-tracing/overview/

> Istio leverages Envoy’s distributed tracing feature to provide tracing integration out of the box. Specifically, Istio provides options to install various tracing backend and configure proxies to send trace spans to them automatically. See Zipkin, Jaeger and Lightstep task docs about how Istio works with those tracing systems.

---
Tags: kubernetes, istio
---


title: Docker performance when running on LVM

text:
# Question
Title: Docker performance when running on LVM
It seems that when using overlay2 storage driver, docker is much slower when using a LVM compared to without a LVM (ext4 filesystem in both cases, same machine).

**Questions:**

1. Is this intended/expected?
2. Is a LVM a recommended setup for docker usage?
3. Is it worth to try other storage drivers (e.g. devicemapper with direct-lvm)?

# Answer
I'm not an docker expert, just responding from my experience and limited knowledge.

1. It's expected, yes.
2. That's a matter of opinion. I'd say no, but that's very subjective.
3. Yes.

https://docs.docker.com/storage/storagedriver/device-mapper-driver/
> 0 votes

---
Tags: docker, linux, performance
---


# Question
Title: How do I run a CI build in a docker image matching the current `Dockerfile` while being resource-aware?
Given a repository containing a `Dockerfile` that defines the build environment used by the CI pipeline as well as by the developer (e.g. as a Visual Studio Code devcontainer), the CI pipeline shall fulfill the following requirements:

1. The CI pipeline shall build the repository's contents in the context of a docker image built from the very `Dockerfile` present in the working branch (or the result of its merge to the target branch where applicable in the context of a pull request).

* Rationale: Builds shall be deterministic so that old repository versions shall be built with their original docker image, not with the newest one.
* Rationale: Changes to the `Dockerfile` shall be considered automatically without the need for manual user intervention (i.e. local docker build followed by a manual push).

2. The CI pipeline shall reuse an already built docker image if the applicable `Dockerfile` has already been "baked" into such an image pushed to the registry.

* Rationale: Building a docker image on each commit is resource-consuming (time, energy).

I couldn't find an existing best practice to implement that out of the box (my CI environment being Azure DevOps Pipelines if it matters) so I came with the following concept:

* Calculate the `Dockerfile`'s hash.
* Load `docker_image_name:$hash` from the docker registry.
* If the load fails, build `docker_image_name:$hash` from the `Dockerfile` and push it to the docker registry.
* Use `docker_image_name:$hash` (from the registry / from the local cache) to run the CI pipeline (using Azure's container jobs in my case).

Questions:

1. Does this procedure make sense as a solution to my use case?
2. I can't imagine being the first to realize this use case. Is there an existing mechanism (as part of the docker utilities, as part of the Azure DevOps Pipelines framework or from something completely different) that fulfills my needs?

# Answer
> 0 votes
> Does this procedure make sense as a solution to my use case?

vscode devcontainers are one of the greatest inventions in the DevOps space and I can't believe more people are not talking about them. I think having the local dev environment and the pipeline in sync makes a lot of sense. Though I think the procedure you outlined above could be simplified.

> I can't imagine being the first to realize this use case. Is there an existing mechanism (as part of the docker utilities, as part of the Azure DevOps Pipelines framework or from something completely different) that fulfills my needs?

I'm currently doing this in some of my side projects. It is also supported on azure.

# Answer
> 0 votes
Docker has this capability built-in and you can use it in a variety of ways.

One way would be to keep a "cache" tag for every build. This is good if your repo normally doesn't have a lot of parallel work being done.

```
docker pull ${MY_IMAGE}:cache || true
docker build --cache-from ${MY_IMAGE}:cache -t ${MY_IMAGE}:${VERSION} -t ${MY_IMAGE}:cache .
docker push ${MY_IMAGE}:${VERSION}
docker push ${MY_IMAGE}:cache

```

If your repo does have a lot of parallel work being done, don't create a cache tag, instead use the latest version.

```
docker pull ${MY_IMAGE}:latest || true
docker build --cache-from ${MY_IMAGE}:latest -t ${MY_IMAGE}:${VERSION} .
docker push ${MY_IMAGE}:${VERSION}

```

This is basically the following the process you outlined in your question but instead, we are relying on docker to do the work for us. The first step is to pull the image layers down locally. This is faster (usually) than building a new image and if your CI/CD is setup correctly should already be present for the use of caching.

Then the `--cache-from` flag tells Docker to use that image as cache. Which will prevent Docker from building any layers that haven't changed.

---
Tags: docker, continuous-integration, dockerfile, azure-pipelines
---


# Question
Title: Vscode/pytest gives me an error when importing
I asked this question on the regular stackoverflow but i think you guys will be much more competent about this topic. My guess is that is some sort of python setup issue.

When I write an import line like this `from mypackage import something` and run it using vscode tools it gives my an error, when I run it using venv python it works. Same for pytest, I have to run it like this: `python3 -m pytest tests` for it to work. The main thing that i'm trying to accomplish is to be able to run/debug stuff from vscode.

The steps I took for it to work:

* Create venv & avtivate it
* Turned my project into a package
    + Create setup.py
    + pip3 install -e .
* Create a launch.json file

The launch.json file:

```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: Current File",
      "type": "python",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal",
      "args": ["-q", "data"]
    }
  ]
}

```

And the setup file:

```
from setuptools import setup

setup(
  name='mypackage',
  version='0.1.0',
  packages=['mypackage'],
  scripts=['bin/script'],
  license='LICENSE.txt',

)

```

Expected behaviour:

* pytest not to give an import error
* vscode not to give an import error

What I get:

* works only when I explicitly run it like this: `python3 main.py`

Trying to solve it for a solid hour. Many many many thanks for helping!

# Answer
> 0 votes
I'm guessing you created and activated in your terminal?

You need to tell vscode about the venv. It's pretty good at finding and using them but sometimes it dectects the wrong one.

At the bottom of the vscode window you should see the environment listed. If its the wrong one click it and find the right one.

Also your `launch.json` and `setup` file seems wrong.

The `program` should probably be `script` or `python3 ${file}` in `launch.json`.

In your setup file `scripts` should be `scripts=bin/my-cool-program`. Then you can change `program` in `launch.json` to `my-cool-program`. You should also be able to run it from your terminal like `$ my-cool-program -q data`.

This is a great way to learn, but it's not how I would create a CLI program today in python. I think you would be better off using `poetry` and `click`. Here is an excellent guide to "modern" python.

---
Tags: python
---