# Question
Title: Elasticsearch on Docker - file permission issues
I am trying to test LDAP in elasticsearch/kibana by running it in Docker on Windows 10.

I pulled the image down:

```
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.10.0

```

And ran it:

```
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.10.0

```

I did the same with Kibana and everything came up as expected. I then upgraded the elastic licence and started the 30 day trial to get the LDAP features in X-Pack.

I opened a shell to the container and updated the elasticsearch.yml file with my LDAP information and set the path to the role\_mapping.yml file. I also updated role\_mapping.yml file with the LDAP informaiton. I followed the instructions here: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/ldap-realm.html

Now when I restart the elasticsearch container I get the following error then the container halts:

```
uncaught exception in thread [main]
java.lang.IllegalStateException: security initialization failed
Likely root cause: java.security.AccessControlException: access denied ("java.io.FilePermission" "/role_mapping.yml" "read")
at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
at java.base/java.security.AccessController.checkPermission(AccessController.java:1036)
at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:408)
at java.base/java.lang.SecurityManager.checkRead(SecurityManager.java:747)
at java.base/sun.nio.fs.UnixPath.checkRead(UnixPath.java:810)
at java.base/sun.nio.fs.UnixFileSystemProvider.exists(UnixFileSystemProvider.java:524)
at java.base/java.nio.file.Files.exists(Files.java:2514)
at org.elasticsearch.xpack.core.XPackPlugin.resolveConfigFile(XPackPlugin.java:361)
at org.elasticsearch.xpack.security.authc.support.DnRoleMapper.resolveFile(DnRoleMapper.java:86)
at org.elasticsearch.xpack.security.authc.support.RoleMappingFileBootstrapCheck.create(RoleMappingFileBootstrapCheck.java:47)

```

I overwrote the elasticsearch.yml file by copying a version with the LDAP config commented out so I could start the container. When I did this I checked the file permissions and both elasticsearch.yml and role\_mapping.yml have the same:

```
-rw-rw---- 1 elasticsearch root  199 Dec  2 15:51 elasticsearch.keystore
-rwxr-xr-x 1 root          root  568 Dec  2 18:36 elasticsearch.yml
-rw-rw---- 1 elasticsearch root 2301 Nov  9 21:28 jvm.options
drwxrwxr-x 2 elasticsearch root 4096 Nov  9 21:32 jvm.options.d
-rw-rw---- 1 elasticsearch root 8451 Nov  9 21:35 log4j2.properties
-rwxr-xr-x 1 elasticsearch root  502 Dec  2 20:15 role_mapping.yml
-rw-rw---- 1 elasticsearch root  197 Dec  2 20:10 roles.yml
-rw-rw---- 1 elasticsearch root    0 Nov  9 21:32 users
-rw-rw---- 1 elasticsearch root    0 Nov  9 21:32 users_roles

```

I even tried CHMODing the role\_mapping.yml file to 777 but I still get the same result.

I feel like I'm missing something obvious...

# Answer
> 1 votes
I have discovered the issue, the path to the role\_mapping.yml file was incorrect in elaticsearch.yml. I had to use the full path /usr/share/elasticsearch/config/role\_mapping.yml

---
Tags: docker, windows, elasticsearch
---


title: Does GitHub support VFS for Git?

text:
# Question
Title: Does GitHub support VFS for Git?
**NOTES:**

1. I really hope that this question hasn't been asked before and as far as I know, only Azure DevOps Service (Azure DevOps on cloud) and Azure DevOps Server 2019 (Azure DevOps on-premise) fully supports VFS for Git.
2. VFS in this context is Virtualized File System for Git. It is not VFS in Linux. The same virtualized, but this VFS is specific to ease managing large Git repository.

---

For those who don't know VFS for Git, VFS for Git is helpful to ease managing Git because it has virtualized file system that help managing large size repo, especially for those repo that has size \> 2GB.

For more information, please visit the official landing page of VFS for Git: https://vfsforgit.org/

My question is, when will GitHub support VFS for Git? As far as I know, in early 2018, it says it will support but still no further update until now.

# Answer
GitHub doesn't support VFS. There are news articles in 2017 saying GVFS and later VFS would be supported by GitHub. As of today, there is no support and no planned support for it.

My sources:
> 1 votes

---
Tags: git, github
---


# Question
Title: How long is it appropriate to keep old feature branches in git?
I am on a large team with many developers. We have a large codebase that has many feature branches from our large group of developers. We are accumulating many feature branches.

We generally look to git-flow for best practices.

How long should feature branches last?

Is it safe enough and not costly or degrading to performance to keep all of them?

Are there considerations and maintenance commands that developers need to execute every so often to have working, efficient, and responsive git ?

Thanks.

# Answer
> 5 votes
Feature branches should stay until the feature is done, once done the branch must be closed/deleted. Establishing this kind of behavior should be a team goal and usually takes some time, it's just easier to forget about them in the hurry up I'm ready with my pull request mode.

Keeping all of them makes maintainability harder. You might think that each branch follows a naming convention with a map to a JIRA ticket or whatever kind of mapping you have and it's really straight forward to distinguish them, but that's not the case once you have a dozen of them and even more are constantly piling up. I highly doubt performance has anything to do, it's more like a confusion cost switch.

Regarding the commands, I do not think so.

# Answer
> 2 votes
I agree with Recoba20's answer and I just want to add a couple of things.

> We generally look to git-flow for best practices.

This means that

1. at some point you also merge those branches into the mainline (the `master` branch).
2. you are merging with the `--no-ff` flag

If this is the case, then actually keeping the branches doesn't help your process in any way, *I think*. The changes are already in, and if you need a bug fix or a change, that means you will start a new branch from further down the line, and not from the original feature branch (according to git-flow).

One thing that I can see happening is somehow messing up the mainline (or `release-X`), and you need to recreate a set of features brought together. If you already have the branches, i.e. not deleted, you can create a new release branch and merge the correct features back in. If you don't have the branches, that's not that big an issue, because by using `--no-ff` merges, there is a separate commit for when a branch is being merged in. And, as branches are just pointers to commits, you can just create a branch at that particular last commit, and it's just as you have never deleted it in the first place.

> Is it safe enough and not costly or degrading to performance to keep all of them?

I'm not sure `git` itself would have problems with this, given that branches are just refs (a pointer to a commit), but at the same time it wouldn't surprise me for things to be slow in some cases, e.g. `clone`ing.

One issue that I can see happening more likely is performance degradation of some `git` GUIs. For which I'd recommend some lightweight ones; I've used `gitk` for a long time and it's just right for having a quick overview of the commit tree.

> Are there \[...\] maintenance commands that developers need to execute every so often to have working, efficient, and responsive git ?

I would just mention `git branch --no-merged master` for getting a list of branches not merged yet. It doesn't *fix* anything, but gives a visual of what you're working with.

---

Having said that, I suggest you think about your development process more, and consider doing things a bit different. In my experience, most `git` problems are just symptoms of a process that's not quite tweaked for the intentions. `git` is just there and taking the hits. Having long running (days, weeks) feature branches makes it more likely to run into issues when integrating back.

An alternative to this is to merge more often and/or to use feature toggles.

# Answer
> 0 votes
Re „*How long should feature branches last?*

Just as short as possible. Just as long as needed. "Old feature branch" is a contradiction in itself.

We use Scrum with JIRA as ticketing tool. No feature branch lasts more than the 2 weeks sprint period, ever. Our tickets' planned times go from, often, 2 (net working) hour to, almost never, 40 (net working) hours (that's 2 weeks at 50 % net developing time).

Set *Blocked by* in a task if advised. Tasks with no blocker can be done in parallel, by different persons. With such a fine-granular process any dev can easily continue on a ticket (in case of a day-off, sick leave, burndown of an office at another location, etc.) or begin to work on a new one without having to care about prerequisites.

If a task's estimated fulfilment time tends to be longer than two days, it's splitted into smaller tasks.

### Example: Project using Java, JUnit, GitLab, Eclipse, Maven, Jenkins

**Dev Tasks**

* Create Jenkins projects for the branches main, develop, feature, hotfix, release
* Create Git repo(s) (including configuring access right etc.)
* Create Maven project(s) (from within Eclipse), adapt POM declarations accordingly (properties, dependencies, plugins, ...)
* Implement the framework: create packages, interfaces, test classes and classes/enums with empty methods, resources and test resources for a start (this task can also be split into more than one depending on the size of the project)
* Implement functionality (can be split depending on...see above)

**Git tasks (for each of the dev tasks above)**

* If a ticket's status changes from *New* to *In implementation* a feature branch is created.
* If a ticket's status changes from *In implementation* to *Implemented* a review is done.
* If a ticket's status changes from *Implemented* to *Closed* the feature branch is merged and deleted.

---

Re „*Are there considerations and maintenance commands that developers need to execute every so often to have working, efficient, and responsive git ?*

See SO for `git gc`.

In a `git flow init`ialized repo there are basically two of them:

* `git flow feature start <name> [<base>]`
* `git flow feature finish [<name>]`

```
(main) $ git flow init
... 6 times <Enter> to accept the defaults ...
(develop) $ git branch
* develop
  main
$ git flow feature start my-cool-feature
Switched to a new branch 'feature/my-cool-feature'

Summary of actions:
- A new branch 'feature/my-cool-feature' was created, based on 'develop'
- You are now on branch 'feature/my-cool-feature'

Now, start committing on your feature. When done, use:

     git flow feature finish my-cool-feature

(feature/my-cool-feature) $ git branch
  develop
* feature/my-cool-feature
  main
...
(feature/my-cool-feature) $ git status | add | commit | pull | push | gc | ...  # whatever
...
(feature/my-cool-feature) $ git flow feature finish  # without a feature name it finishes the current
Switched to branch 'develop'
Already up to date.
Deleted branch feature/my-cool-feature (was a57868f).

Summary of actions:
- The feature branch 'feature/my-cool-feature' was merged into 'develop'
- Feature branch 'feature/my-cool-feature' has been locally deleted
- You are now on branch 'develop'

(develop) $ git push  # if there's a remote repo
(develop) $ git branch
 1. develop
  main
(develop) $ git flow feature start my-even-cooler-feature
...
(feature/my-even-cooler-feature) $

```

Long story short from the bottom of the page Gitflow Workflow:

> The overall flow of Gitflow is:
>
> 1. A `develop` branch is created from `master` \[now `main`\]
> 2. A `release` branch is created from `develop`
> 3. `Feature` branches are created from `develop`
> 4. When a `feature` is complete it is merged into the `develop` branch
> 5. When the release branch is done it is merged into `develop` and `master` \[or `main`\]
> 6. If an issue in `master` is detected a `hotfix` branch is created from `master`
> 7. Once the `hotfix` is complete it is merged to both `develop` and `master` \[or `main`\]

---
Tags: git
---


# Question
Title: Ansible URI module and skip SSL validation
I have a playbook which looks like

```
- name: CURL post example
  uri:
    url: "https://dev-box.local/api/"
    method: POST
    body: '{
           "max_conns": 0,
           "max_fails": 2,
           "fail_timeout": "3s"
           }'
    body_format: json
    validate_certs: no
    return_content: yes
    force_basic_auth: yes
    headers:
      Content-Type: "application/json"

```

but during the execution I'm getting

```
 FAILED! => {"changed": false, "connection": "close", "content": "{\"status\":403,\"message\":\"Forbidden\"}\n", "content_length": "37", "content_type": "application/json", "date": "Thu, 03 Dec 2020 21:03:13 GMT", "elapsed": 0, "json": {"message": "Forbidden", "status": 403}, "msg": "Status code was 403 and not [200]: HTTP Error 403: Forbidden",

```

when I will do the same call as the `curl -k` from the command line on the same box as ansible it works fine.

Any thoughts on that?

# Answer
You seem to be passing `force_basic_auth: yes` but no `user`, nor `password`.

Example from the Ansible docs:

```
- name: Create a JIRA issue
  uri:
    url: https://your.jira.example.com/rest/api/2/issue/
    method: POST
    user: your_username
    password: your_pass
    body: "{{ lookup('file','issue.json') }}"
    force_basic_auth: yes
    status_code: 201
    body_format: json

```

The 403 is usually Basic Auth failing. If it's not, it could be the API server you're running requiring some sort of authentication.

If the `curl -k` command includes something like `https://user:password@dev-box.local/api/` or the `--user <user:password>`, it should work. Or maybe it's using data from `.netrc`?

I hope this helps.
> 1 votes

---
Tags: ansible
---


# Question
Title: Docker prunes image and networks by itself
I have a script which performs backup of several docker volumes during the night.

It starts by stopping the containers that use these volumes, then it creates a new container with all the volumes mounted and back them up with borg. Finally it restarts the containers.

Sometimes the scripts runs into weird issues, like a container can not start because its image or a network it uses is missing. Is it possible that docker daemon prunes them while my backup script is running? How can I disable it?

I could not see anything in daemon logs.

# Answer
I noticed that you have the `docker run` command with `--rm` option. In the Docker docs it says:

> If you set the --rm flag, Docker also removes the anonymous volumes associated with the container when the container is removed. This is similar to running docker rm -v my-container

Perhaps this is why the volumes are being deleted?
> 1 votes

# Answer
No, docker does not automatically prune networks or images. That is left to the user to implement with their own tooling or scripting. It is possible for docker-compose to remove networks, but only when running a `docker-compose down`, and that doesn't remove networks. You'll need to search your own environment to see what you have running that performs a prune.
> 0 votes

---
Tags: docker
---


# Question
Title: Can I build docker image containing ARM executable when running docker build on non-ARM architecture?
I have built on an x86-based Windows laptop a Docker image to be run as a container on an ARM-based architecture (Raspberry Pi 4).

Due to ending up with an x86 executable when this is built in the Dockerfile, as much as possible, including the library and app build, is deferred until the container actually runs on the Pi.

However, this seems absurd in that the build must be done each time the container runs (which it may on many Pis). No doubt it also needlessly increases the container's size (which is less important, but still annoyingly sub-optimal)

So in summary, I wonder if there is a way to run gcc in the Dockerfile and indicate that the target architecture is ARM and not the laptop on which the docker build is running.

My Dockerfile currently comprises :

```
FROM arm32v7/ubuntu:latest

# Defined only while image is being built
ARG DEBIAN_FRONTEND=noninteractive

# Set in container
ENV TZ=Europe/London

ADD ./src /app
WORKDIR /app

# Development only :
#
#   vim
#
RUN apt-get -y update \
 && apt-get -y upgrade \
 && apt-get -t install apt-utils \
 && apt-get -y install tzdata \
 && apt-get -y install dh-autoreconf \
 && apt-get -y install libcurl4-gnutls-dev \
 && apt-get -y install libexpat1-dev \
 && apt-get -y install make \
 && apt-get -y install gettext \
 && apt-get -y install libz-dev \
 && apt-get -y install libssl-dev \
 && apt-get -y install libghc-zlib-dev \
 && apt-get -y install git \
 && apt-get -y install build-essential \
 && apt-get -y install vim \
 && git clone https://github.com/eclipse/paho.mqtt.c.git

CMD ["/bin/bash", "myapp.sh"]

```

and myapp.sh comprises :

```
#!/bin/bash

# Build Paho MQTT library
#
cd /app/paho.mqtt.c
make

# Build the experiment app
#
cd /app

gcc -L/experiment/paho.mqtt.c/build/output -o myapp -lpaho-mqtt3a main.c

./myapp

```

I would have thought the first line "FROM arm32v7/ubuntu:latest" in the Dockerfile would tell gcc that the target architecture was ARM, but evidently not!

P.S. I know I could manually build the app outside Docker on a Pi, and simply copy the ARM executable into the Docker image. But I would rather the the app build is included as part of the image build if possible.

# Answer
> 1 votes
I've not tried this myself, but it seems that you can use docker `buildx` to build for multiple architectures: https://www.docker.com/blog/multi-arch-images/.

# Answer
> 1 votes
You can either:

1. cross compile the image
2. perform the build within an emulator like qemu using binfmt\_misc
3. run the build on each platform

I've done a fair bit of cross compiling in Go, pretty sure there's the ability to do that in gcc. Just note that you'll need to include all the libraries for those other platforms too, which may get complicated. Therefore a statically compiled binary my be easiest. Doing this, I then have a multi-stage build where the last stage is for the target platform and only includes copy commands to copy in the cross compiled binary. For controlling the platform on each stage, there's a `FROM --platform` option.

With binfmt\_misc, that needs to be installed with the `--fix-binary` option that will show a `F` flag in the `/proc/sys/fs/binfmt_misc/*`. If it's not installed with this option, trying to run a container for another platform will output a "file not found" error as binfmt searches for the interpreter inside the container filesystem rather than the host filesystem. Note that this is already setup on Docker Desktop.

Once built, you can push the resulting image to the registry as a multi-platform image, and the appropriate image will pulled under the same name based on the platform performing the pull. The easiest way I've found to create multi-platform images is to use buildx which comes bundled into recent versions of docker.

I demonstrate each of these options in this presentation.

---
Tags: docker, dockerfile
---


# Question
Title: One Repository for Kubernetes configuration or one configuration per application repository
We are currently migrating our Services to a Kubernetes environment.

My question is if the configuration yaml file for each application

* should be in the repository where the application source itself is stored,
* or if there should be a centralized repository just for all the configuration files.

Currently I'm drifting more towards a centralized repository holding all configs, as dependencies on different versions of applications / services can be managed there. Another thing is that a change in the configuration should not trigger a rebuild of the application itself and this is also easier if the configuration and the application repositories are not the same.

# Answer
> 1 votes
If you're just migrating I'd also recommend using `helm`.

When using `helm` create the chart definition within the source code repository of the application, https://helm.sh/docs/helm/helm\_create/.

With an increasing number of services it can become harder and harder to manage so people have started to embrace a "monorepo" that contains a definition of the all the `helm charts` they currently have deployed and their respective versions. This way you can easily track when a version of service A was bumped and when a version of service B was bumped. https://www.infracloud.io/blogs/monorepo-ci-cd-helm-kubernetes/

# Answer
> 0 votes
I don't think there is a right answer here, because there are pros and cons to both options.

A centralized approach is potentially DRYer and easier to manage but isn't connected to the apps themselves, so a change in the Kubernetes repository could make an app fail and the developer would be none the wiser.

A distributed or per repository approach allows you to delegate part of the work responsibility/powers to the developers of that repository but has the fragmentation problem (i.e. if your organization changes the way a commonly used Nginx deployment is done, it has to be updated in all repositories).

I'm sure there are more reasons and opinions, but in my view, these are the biggest points (besides what you already described). I hope this helps!

---
Tags: kubernetes, configuration-management, configuration
---


# Question
Title: Disabling of docker build cache - common practice for large organizations?
I've been working with a large company that currently disables the docker build cache for CI/CD. Their justification is that they are managing many projects, so caching would be cumbersome.

This results in builds that are considerably slower than our local docker builds. They also regularly hit limits in downloading from docker registries. And the DevOp engineers have no incentive to optimize for caching, so the builds run poorly when running docker with a cache.

Is the disabling of the docker build cache considered to be a common (or best) practice for large organizations? Are there resources that spell out the best practices in such situations? And if this is not the best place to ask this question, where should I go?

# Answer
> 2 votes
I guess each organization does what is best for them, but one of Docker's best practices is to leverage build cache.

Applied to a large company, I'd say that if they would use Docker caching (correctly) and save a couple of seconds/minutes on every build. They would, given their size, save many hours/days of Engineering time, which amounts to a lot of money. Also, when a build takes too long, it breaks the flow of the individual, which means more context switching on the side of the engineer, which usually leads to less productivity.

---
Tags: docker
---


title: Docker mounts files as uid 1001

text:
# Question
Title: Docker mounts files as uid 1001
I have a Docker image that runs a PHP application. Everything works fine on my machine and the ones of my colleagues.

However, some colleagues got a new computer that runs on Ubuntu 20.04 and by default the user on these computers have the user id 1001. If I run the `id` command on these computers I get 1001 for the user id and group id. So, when they start the container, the files are chown with 1001:1001 and the code cannot be executed and no files can be written in the document root of the project.

How to fix this issue?

# Answer
Sounds like you are using a host volume. Docker doesn't perform any uid/gid mapping on the files mounted into the container, this is how bind mounts work in Linux. On Windows and Mac, Docker Desktop may do a convenience mapping to eliminate permission issues, but that's a feature of those platforms that doesn't exist in Linux. You'll either need to configure the container to work with the volume mount, make the image match the uid/gid on the host, or avoid host mounts.

For the first option, in development I often start containers as root, have them adjust the container user to match the volume owner, and then use gosu to drop from root to the container user to run the app. I implement this and include an example in my base image repo. See the `bin/fix-perms` script that adjusts the container uid/gid, `bin/entrypointd.sh` that looks for the RUN\_AS variable to call gosu, and `examples/nginx/entrypoint.d/10-fix-perms.sh` that runs the fix-perms script.
> 3 votes

# Answer
Ideally dont run docker as superuser(root). You should create a user within dockerfile and chown the file system with that user. You can create a user and then add access to that user on the file system. In the below example there is appuser , with ownership to src

```
FROM ubuntu:latest
RUN useradd -r -u 1001 -g appuser appuser
RUN chown -R appuser.appuser /src
USER appuser
CMD ["appuser", "/src/index.js"]

```

Its not recommended to run as root You could also run as any user (Say root id = 0) if needed from externally

```
docker run -d --user 0 ubuntu:latest

```

You should never relay on gid/uid of the linux user outside the container.
> 1 votes

---
Tags: docker, permissions
---


title: How to change Ip for a DNS

text:
# Question
Title: How to change Ip for a DNS
I'll be very direct. I'm tired to search this and do not found anything about it. There is any way to change a lan ip to a dns (not chaging 'hosts' file)? Example: I've a centOs running in machine A and code any types of code in machine B. Either machine A and B are in same local area network and have differetns IP's. So, Machine B has 10.0.0.2 as IP and Machine B has 10.0.0.3. Machine A has docker on it, and I can acess from machine B as 10.0.0.2:xxxx What I'm trying to accomplish is: Machine B insted of reaching machine A with IP (10.0.0.2:xxxx) I'm intend to reach with anyname.dsv.local.

# Answer
> 1 votes
Yes you can do it. You have to set up BIND as a Private Network DNS Server.

---
Tags: docker, dns
---


# Question
Title: Terraform ignore_changes block on JSON-encoded attribute
I'm currently trying to get CloudWatch logging and DMS configuration working smoothly in my module by ignoring certain attributes on `replication_task_settings`. Right now, I have a DMS replication task that looks like the following:

```
resource "aws_dms_replication_task" "main" {
  migration_type            = "full-load-and-cdc"
  replication_instance_arn  = var.replication_instance_arn
  replication_task_id       = "${var.environment}-${var.customer}-dms-replication-task-ongoing-main-${var.engine}"
  source_endpoint_arn       = var.source_endpoint_arn
  target_endpoint_arn       = var.target_endpoint_arn
  replication_task_settings = jsonencode(local.task_settings)
  table_mappings            = jsonencode(local.table_mappings)
  tags                      = merge({}, local.additional_labels)

  lifecycle {
    ignore_changes = [
      replication_task_settings
    ]
  }
}

```

With this configuration, I'm ignoring all future changes to `replication_task_settings`. What I would like to do is only ignore changes to only `Logging.CloudWatchLogGroup` and `Logging.CloudWatchLogStream` (not all of the task settings) since DMS creates these for you and you can't change them. The problem is that the `replication _task_settings` is a JSON-encoded attribute. If I try to do `ignore_changes = [replication_task_settings["Logging"]["CloudWatchLogStream"]]`, I get this error:

```
Error: Invalid index

  on modules/repl-ongoing/main.tf line 250, in resource "aws_dms_replication_task" "main":
 250:       replication_task_settings["Logging"]["CloudWatchLogStream"]

This value does not have any indices.

```

If I try to decode the JSON by doing: `ignore_changes = [jsondecode(replication_task_settings)["Logging"]["CloudWatchLogStream"]]`, I get the following error:

```
Error: Invalid expression

  on modules/repl-ongoing/main.tf line 250, in resource "aws_dms_replication_task" "main":
 250:       jsondecode(replication_task_settings)["Logging"]["CloudWatchLogStream"]

A single static variable reference is required: only attribute access and
indexing with constant keys. No calculations, function calls, template
expressions, etc are allowed here.

```

Is there a way I can ignore changes to specific properties of JSON-encoded attributes? Or is there another workaround with DMS tasks that I have to go with?

# Answer
Due to how that resource type is designed, from Terraform's standpoint `replication_task_settings` is just an opaque string and so Terraform can either detect that the string has changed (the default) or ignore changes to the string as a whole.

There is no way to ignore changes to only part of a string, because Terraform implements `ignore_changes` by taking the previous value of that argument instead of the new value. Terraform doesn't and can't know how to construct an new string that combines some characters from the old string and some characters from the new string, because it has no awareness of the meaning of that string.
> 3 votes

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


# Question
Title: Kubernetes namespaces with RBAC: sufficient for tenant isolation in a public environment?
Initially namespaces have been created to enable logical partitioning of a single Kubernetes cluster in order to prevent naming conflicts. Over time, this changed. While this article from 2016 sais

> Any user or resource in a Kubernetes cluster may access any other resource in the cluster regardless of namespace. So, if you need to protect or isolate resources, the ultimate namespace is a separate Kubernetes cluster \[...\]

With RBAC it's now possible to set permissions on a specific namespace and thus restrict authenticated users to specific namespaces and their resources.

So, if I get this right, the quote from above is outdated. With RBAC in place it's possible to make sure a user or resource may only access stuff in their own namespace. **Is that correct?** I struggle to find recent documentation that explicitly sais that it's fine use namespaces (with RBAC) to seperate tenants from accessing each others stuff. Does anyone use namespaces and RBAC to seperate (unfriendly) tenants? Is there any clear statement about this from the CNCF?

If so, purely from a security perspective, what level of isolation are we talking about here? Clearly, the cluster IP would be accessible to all tenants and even with quotas in place I can imagine simple DOS attacks that might break a single cluster. Simple RBAC misconficutions might leak data between tenants and of course there's also the risk of implementation error and future exploitation. But if we consider those things "acceptable", are namespaces really a good tool for tenant isolation?

# Answer
There's an active SIG devoted to multitenancy so I have a hard time believing that nothing has been written about it in 4 years.

Namespaces are only part of the answer. That isolates kubernetes objects impacting other kubernetes objects, but you also need to worry about shared resources like the ingress namespace. If containers share worker nodes, then there are resource limits to enforce. And the default network model used by kubernetes is flat with DNS exposing services and containers in other namespaces and an open network policy allowing any container to talk to any other container. The kubernetes API is also shared in a multi-tenant environment, allowing a DoS to the kubernetes infrastructure itself. And if users are allowed to run containers with added capabilities, privileged access, host bind mounts, host namespaces, and probably many other features, they can escape the container isolation and get root access on the host running the containers. None of this is trivial to implement securely.
> 1 votes

---
Tags: kubernetes
---


# Question
Title: In a multistage Docker build, should the WORKDIR be deleted?
My Dockerfile contains this:

```
### STAGE 1: Build Angular app ###
FROM node:14.15 AS build
WORKDIR /usr/src/app
COPY src/hub/package.json ./
RUN npm cache verify
RUN npm install
COPY src/hub/ .
RUN npm run-script build-azdev
RUN npm prune --production

### STAGE 2: Run Angular app in nginx ###
FROM nginx:1.19-alpine
COPY /scripts/nginx/nginx.conf /etc/nginx/nginx.conf
RUN rm -rf /usr/share/nginx/html/*
COPY --from=build /usr/src/app/dist/* /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

```

Once `COPY --from=build /usr/src/app/dist/* /usr/share/nginx/html/` is done, should the contents of WORKDIR (/usr/src/app) be deleted once Stage 2 is done building?

# Answer
> 2 votes
When creating an image using a Dockerfile, docker layers are created for each step. The description of layers can be found on the official docker page.

Accordingly, when using Multistage to create an image, it introduces a new build step that can be named using an alias in the FROM statement, and all layers except the image layer created via the last FROM statement are deleted.

After build your image, check if the layer that contains WORKDIR whether exists or not using docker image inspect. I think you probably know the unique layer value for each step.

You can see the image consists with which layers. e.g.,

```
$docker image inspect [OPTIONS] 464503b73bfe # IMAGE
[
    {
        "Id": "sha256:464bf1...46c",
        ...

        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:26711...8fcf",
                "sha256:6c5a51...56e0"
            ]
        },
        ...

```

---
Tags: docker
---


# Question
Title: WordPress Site Health errors when using Docker and Nginx
I am trying to setup a production environment for multiple WordPress sites using Docker, Nginx reverse proxy, and Let's Encrypt.

I have 3 containers for the proxy group using the jwilder/docker-gen, jwilder/nginx-proxy, and jrcs/letsencrypt-nginx-proxy-companion images.

I also have separate containers for mysql and WordPress.

Everything runs ok and the site loads. However, I am getting the following Site Health Errors in WordPress:

> The REST API request failed due to an error. Error: cURL error 28: Connection timed out after 10000 milliseconds (http\_request\_failed)

> The loopback request to your site failed, this means features relying on them are not currently working as expected. Error: cURL error 28: Connection timed out after 10001 milliseconds (http\_request\_failed)

> Background updates ensure that WordPress can auto-update if a security update is released for the version you are currently using.
>
> Warning Could not confirm that the wp\_version\_check() filter is available

I have confirmed that cURL is working within the WordPress container and also that all containers are on the same docker network.

I have tried disabling all plugins in WordPress and using default theme (twentytwenty).

I am able to update plugins and themes.

I have updated my php settings in the WP container so that max\_execution\_time = 600 and memory\_limit = 1024M.

This same site runs on a LAMP stack and all Site Health tests pass.

I will also mention that the site also seems slower to respond when running in the Docker container.

I am thinking that this must have something to do with Nginx, but cannot figure out what it could be. Any help would be greatly appreciated.

Included are my docker-compose configurations.

For Nginx:

```

services:
  nginx:
    image: jwilder/nginx-proxy
    container_name: nginx
    restart: always
    labels:
      com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: 'true'
    ports:
      - 80:80
      - 443:443
    # environment:
    #   - VIRTUAL_PROTO=https
    #   - VIRTUAL_PORT=443
    volumes:
      - /srv/nginx/data/conf.d:/etc/nginx/conf.d
      - /srv/nginx/data/vhost.d:/etc/nginx/vhost.d
      - /srv/nginx/data/html:/usr/share/nginx/html
      - /srv/nginx/data/certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      - proxy

  dockergen:
    image: jwilder/docker-gen
    container_name: dockergen
    command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
    volumes:
      - /srv/nginx/data/conf.d:/etc/nginx/conf.d
      - /srv/nginx/data/vhost.d:/etc/nginx/vhost.d
      - /srv/nginx/data/html:/usr/share/nginx/html
      - /srv/nginx/data/certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
    networks:
      - proxy

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt
    depends_on:
      - nginx
      - dockergen
    environment:
      NGINX_PROXY_CONTAINER: nginx
      NGINX_DOCKER_GEN_CONTAINER: dockergen
    volumes:
      - /srv/nginx/data/conf.d:/etc/nginx/conf.d
      - /srv/nginx/data/vhost.d:/etc/nginx/vhost.d
      - /srv/nginx/data/html:/usr/share/nginx/html
      - /srv/nginx/data/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - proxy

networks:
  proxy:
    driver: bridge

```

For WP:

```

services:

  db:
    container_name: $DB_CONTAINER
    image: mysql:5.7
    restart: always
    volumes:
      - ./db_data:/var/lib/mysql
    environment:
      #MYSQL_RANDOM_ROOT_PASSWORD: 1
      MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD

  wp:
    container_name: $WP_CONTAINER
    image: wordpress:latest
    depends_on:
      - db
    expose:
      - 80
    restart: always
    extra_hosts:
      - "my-domain-name.ca:192.168.80.2"
    volumes:
      #- ./wp-config.php:/var/www/html/wp-config.php:rw
      - ./wp-content:/var/www/html/wp-content:rw
      - ./config/php-config.ini:/usr/local/etc/php/conf.d/php-config.ini
    environment:
      WORDPRESS_DB_HOST: $DB_CONTAINER
      WORDPRESS_DB_NAME: $DB_NAME
      WORDPRESS_DB_USER: $DB_USER
      WORDPRESS_DB_PASSWORD: $DB_PASSWORD
      WORDPRESS_TABLE_PREFIX: $WP_TABLE_PREFIX
      VIRTUAL_HOST: $VIRTUAL_HOST
      VIRTUAL_PORT: $VIRTUAL_PORT
      LETSENCRYPT_HOST: $LETSENCRYPT_HOST
      LETSENCRYPT_EMAIL: $LETSENCRYPT_EMAIL
      WORDPRESS_CONFIG_EXTRA: |
        define('ALTERNATE_WP_CRON', true);
        define('FORCE_SSL_ADMIN', true);

networks:
  default:
    external:
      name: nginx_proxy

```

# Answer
> 1 votes
This was so simple I've been kicking myself ever since I figured out what was wrong.

In the WP stack docker compose file this line was correct, but missing the 'www'.

```
extra_hosts:
      - "www.my-domain-name.com:192.168.80.2"

```

In my WordPress setup the site URL included the www. So I was right to point the domain name to the IP of the Nginx container, but not including the full URL as specified in WP was causing the issue.

For anybody experiencing WP Site Health issues when using Docker, Nginx the solution is to use the "extra\_hosts" directive in the wordpress container setup and point the IP of the Nginx container to the WordPress site URL.

---
Tags: docker, nginx
---


# Question
Title: Why is it necessary to have virtual machines to run multiple server instances?
I'm trying to learn about virtualization and containers. In an educational video it is said that the introduction of virtual machines was a big deal because it made companies available to run multiple server instances on the same machine, so they did not have to necessarily buy a new machine just to run a new instance.

But what if I have a Node.js server application? I could run multiple of those on the same machine without any kind of virtualization. Why is even running multiple instances necessary? Why were virtual machines needed? My best guess is that Node.js is designed to support running multiple instances (the instances doesn't "know" about each other), therefore they are not needed, but back then the servers that they used would have "known" about each other if they weren't separated by virtual servers.

Do people do the same using containers? If I have a microservices architecture, and let's say that I only have one computer, am I using containers only to check whether they run correctly in different environments, or do I create multiple of even the same microservice?

Please excuse my sloppy wording, I mainly try to get what is it that I'm actually missing / misunderstanding, and I try to convey my abstract, high-level understanding of the issue.

Link to video: https://youtu.be/JSLpG\_spOBM?t=77

# Answer
> 3 votes
## Multiple apps on the same server

> But what if I have a Node.js server application? I could run multiple of those on the same machine without any kind of virtualization.

Yes, you can run multiple apps or multiple instances of the same app on a server. The problem is that these apps will *interfere*.

Some examples of resources, that might interfere:

* They would all like to listen to the same **port** e.g. 8080.
* If they need more **memory**, they will eventually fight about the same memory.
* If the apps is busy, they will fight about the same CPU resource.
* They all would like to write logs to the same files on the file system.
* They all might want to save data to the same place on the file system.

This needs to be managed in some way, and we don't want to do it manually.

With Virtual Machines on the same server, or Containers on the same server, each instance get its own IP-address, each instance can listen to what port it wants, e.g. all can listen to 8080. You can bound how much memory an instance has, e.g. 1GB - so if an app leaks memory, it does not affect the others. You can also bound how much CPU each instance can use, so they only use their fair share. Each instance has its own view of the filesystem, so all instances can write to the same path (as they see it) - even though it is technically different places.

## Multiple instances - Availability

> Why is even running multiple instances necessary?

What would you do when you need to patch the server and need to restart it? How will you upgrade your app to a new version? What happens if the hardware on your server crash? What happens when your single instance can not handle all the traffic?

The answer to all those questions, typically is: run more than one instance of your app, and let a load balancer forward the traffic to your instances that are alive.

## Why virtualization?

> Why were virtual machines needed?

They are not really needed. This is more about economics, a way to use your expensive hardware more efficiently.

If you start a new project, but a server - the server is very powerful and expensive. If you only start a Node.js app on this server, it will probably take long time before this Node.js app is so popular that it need to use the full server. It would be better if you could rent only a small part of the server in the beginning - that is how the Cloud with AWS and Google Cloud Platform works.

---
Tags: containers, microservices, node.js, virtualization
---


title: Do Docker containers take up space?

text:
# Question
Title: Do Docker containers take up space?
When I list my Docker images, I can see their sizes:

```
$ sudo docker image ls

REPOSITORY                TAG                          IMAGE ID       CREATED         SIZE
travisci/ci-ubuntu-1804   packer-1606831264-7957c7a9   0a7a71407638   8 days ago      15.6GB
travisci/ci-ubuntu-1804   packer-1593521720-ca42795e   6093ba41f031   5 months ago    12.3GB
travisci/ci-sardonyx      packer-1547455648-2c98a19    d1b323af5b2a   23 months ago   9.02GB

```

However, docker containers do not display the space used:

```
$ sudo docker container ls

CONTAINER ID  IMAGE         COMMAND       CREATED         STATUS         PORTS  NAMES
5794ae898b68  6093ba41f031  "/sbin/init"  10 minutes ago  Up 10 minutes         travis
762e3f8df2da  0a7a71407638  "/sbin/init"  4 hours ago     Up 4 hours            distracted_noyce

```

Of course, I understand that if you're writing to containers, some space *will* be used on the hard drive.

But when you create a container, **does Docker actually clone the image** before booting up the container? Or does it work with diffs, only storing the differences between the image and the current container disk state?

And, **how can I see the actual disk space used by a container?**

# Answer
> 12 votes
Yes, docker containers when they are running can take up some space as per your workload and application but as mentioned in the other answers - containers are built over layered filesystem therefore only extra space they consume is from some file/object they create/download during runtime which is not the part of base image like some debug log files, etc.

For ex. - When you run 100 containers of a base image of size 1GB, docker will not consume 100 GB of disk space as it leverages layered filesystem and top immutable layer is shared across all containers of same image.

When you stop and remove (yes!, remove explicitly or use `--rm` flag with `docker run` command) a container then it's space is reclaimed.

To check space used by containers (and other objects), you can use:

`$ docker system df` and for detailed info. use verbose flag `$ docker system df -v`

Initially when you start a container the SIZE column will show 0B but as soon as you start writing to the disk SIZE will change.

EDIT: added more info. as suggested by @Benjamin in comments

# Answer
> 3 votes
> does Docker actually clone the image

Typically no, it uses a layered filesystem, by default that's overlay2 on my systems. A decent example of this comes from the arch wiki:

> * The lower directory can be read-only or could be an overlay itself.
> * The upper directory is normally writable.
> * The workdir is used to prepare files as they are switched between the layers.
>
> The lower directory can actually be a list of directories separated by :, all changes in the merged directory are still reflected in upper.
>
> Example:
>
> ```
> # mount -t overlay overlay -o lowerdir=/lower1:/lower2:/lower3,upperdir=/upper,workdir=/work /merged
>
> ```

---

> how can I see the actual disk space used by a container?

Docker will show you the disk used by all containers in a `docker system df`.

```
$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          183       4         37.59GB   37.34GB (99%)
Containers      7         3         2.23kB    1.114kB (49%)
Local Volumes   10        1         4.816GB   305.8MB (6%)
Build Cache     511       0         20.49GB   20.49GB

```

For a container, this number is not static (unlike images that are read only), so I don't think this shows in any of the inspect commands. But you can see the underlying filesystems used:

```
$ docker container inspect 056 --format '{{json .GraphDriver}}' | jq .
{
  "Data": {
    "LowerDir": "/home/docker/overlay2/ba813e6876186f8792d263ced7dc912921870393a085644188a8adadcf73d3e6-init/diff:/home/docker/overlay2/22281f31287edf3342709add6123436540bd04dea60e474c961421e47b2dd58f/diff:/home/docker/overlay2/6a7a1eee38c2496928dff4741c2f9a1365f177a3e620ef7cf8adb816bba69b55/diff:/home/docker/overlay2/fcf371f07f06a42d328027281afb52c8044000cb51c4bb01a1f0dca2701062ec/diff:/home/docker/overlay2/89f8b12195e051bc439ac66d2bb299975884cdb229146dd570b1cac4011a08e6/diff:/home/docker/overlay2/d5a7a5c1c11746080d802b4dd076fd4d775099cb16b73d82c06db71e93b4e0c5/diff",
    "MergedDir": "/home/docker/overlay2/ba813e6876186f8792d263ced7dc912921870393a085644188a8adadcf73d3e6/merged",
    "UpperDir": "/home/docker/overlay2/ba813e6876186f8792d263ced7dc912921870393a085644188a8adadcf73d3e6/diff",
    "WorkDir": "/home/docker/overlay2/ba813e6876186f8792d263ced7dc912921870393a085644188a8adadcf73d3e6/work"
  },
  "Name": "overlay2"
}

```

In this case, I can look at the disk usage of UpperDir to see how much space is used by that container:

```
$ sudo du -sh /home/docker/overlay2/ba813e6876186f8792d263ced7dc912921870393a085644188a8adadcf73d3e6/diff
80K     /home/docker/overlay2/ba813e6876186f8792d263ced7dc912921870393a085644188a8adadcf73d3e6/diff

```

---

The actual disk space used by a container includes the filesystem changes made by the container, since overlay is a copy-on-write filesystem. Each file changed is first copied to the container specific filesystem, even for a timestamp, permission, or owner change to the file metadata. This allows multiple containers to use the same immutable image layers without seeing changes made by the other containers.

Docker also keeps container logs, stdout and stderr, for each container. These logs are by default unlimited.

What you won't see is a full copy of the image filesystem, **unless** the overlay and similar graph drivers are unavailable to the docker engine. The fallback on an unsupported host filesystem, or kernel missing the needed features, is to use the `vfs` graph driver in docker, which I believe is the same as the `native` snapshotter in containerd. I see this happen occasionally with a docker-in-docker build environment where you cannot run an overlay filesystem on top of the overlay container filesystem (the fix there is typically to mount a volume that is on a supported filesystem outside of the container's overlay filesystem).

# Answer
> 0 votes
Docker containers are processes, does a process use disk space ? nope (at least not in itself).

The space used is the space when you put the program on disk first (the container image here).

Starting a container multiple times behave as starting bash/zsh/ multiple times when you login/ssh on different terminals/sessions.

One particularity of containers, more precisely of overlayfs, is the layers, if you pull two images for services based on the same base image, the initial layer won't be downloaded twice.

A rought illustration:

```
- Ubuntu 20.04
|- redis (FROM ubuntu 20.04)
|- apache2 (FROM ubuntu 20.04)

```

You can get image for apache2 and redis and get only 3 layers on disk, the base ubuntu 20.04 will be reused.

Refer to BMitch's answer for details

---
Tags: docker
---


# Question
Title: any way to limit "docker logs" output by default?
**Context***

I forgot to pass the "--tail" options to the "docker logs" command when inspecting a running container. The affected container dumps tens of millions of logs.

The command line was something like:

```
  $ docker logs contianer01 | vim -

```

When executing such line my server becomes completely unresponsive for minutes due to exhaution of free RAM memory with peak loads beyond 60x100%. I loose control of the terminal and ssh connection fails.

***Question***: Is it any tunning in docker to "fail fast" and forbid such big log outputs in first place (maybe tunning ulimits for the docker daemon in some config file)

***NOTE***: Probably "ulimit", "resource-control" and "linux" tags must be added to this question but I have not enough "reputation".

# Answer
> 1 votes
One way to limit docker logs is to specify limits in docker daemon's config file.

You can put this in `/etc/docker/daemon.json`

```
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

```

and then restart your docker daemon.

---
Tags: docker, linux
---


# Question
Title: gitlab kubernernetes integration: configuring the installed runner
I connected my existing kubernetes cluster to gitlab using the gitlab integration in myproject/operations/kubernetes on the left tab pane in the gitlab gui.

After having installed helm + gitlab runner from the gitlab GUI applications, the new gitlab runner is visible in the project runners.

What I don't understand from the gitlab documentation is how do you modify the new runner's configuration. You cannot use the gitlab-runner cli, like for a non-kubernetes runner, because the runner in running in a pod, not on the host machine, right?

I am not sure which part of the runner doc applies to my case. What to use if I wanted to make the runner use another executor or build from another image ? (default image of the pod is ubuntu 16 for me).

If you have already installed and configured a runner installed this way, from the GUI, please tell me how. Thank you.

Gitlab 12.9.2 hosted

# Answer
> 1 votes
**Installing kubernetes integration on gitlab**

In Admin Area -\> Overview -\> Runners, the instructions they give are:

1. Install GitLab Runner
2. Specify the following URL during the Runner setup: `https://<your gitlab hostname>/`
3. Use the following registration token during setup: `<insert-token-here>`
4. Start the Runner!

*I'm on version 13.13.0 but I don't remember the instructions changing from version 12.x.x.*

**Project specific runners**

As for your question regarding configuration, I'm a little bit confused if you're looking for something beyond those instructions. If you want to set up a runner specific to a project, you can go to a project then navigate to Settings -\> CI/CD -\> Runners -\> Specific Runners. There, there are more instructions on setting up project-specific runners.

**Further configuring the runner**

**EDIT**: The executor entirely depends on how the runner itself is installed. If it's installed on a kubernetes cluster, then it *must* be the kubernetes executor. That will affect your pipeline. I think you can create another one if you install another one with the runner chart. You can also use Helm Tiller.

---
Tags: kubernetes, gitlab, cicd, gitlab-ci-runner
---


# Question
Title: K8s cluster in peered VPC can't reach RDS cluster
I have two K8s clusters in the same VPC that I want to connect to an MySQL Aurora RDS cluster. One of the clusters can reach the RDS cluster just fine. The other, however, cannot. I'll call these `eks-cluster-working` and `eks-cluster-broken`.

I have a security group allowing traffic to the cluster:

| Type | Protocol | Port range | Source | Description |
| --- | --- | --- | --- | --- |
| MYSQL/Aurora | TCP | `3306` | `sg-1` (eks-cluster-sg-working) | This rule works |
| MYSQL/Aurora | TCP | `3306` | `sg-2` (eks-cluster-sg-broken) | This one does not |

Both `eks-cluster-working` and `eks-cluster-broken` have the same default security groups that AWS creates when making an EKS cluster and they are both on the same K8s version (1.18). The one exception is that `eks-cluster-working` has an extra security group for the load balancer service since it's hosting a web service and the other one (`eks-cluster-broken`) is not. Both clusters have outbound traffic rules that can reach `0.0.0.0/0`.

I have zero firewalls, firewall policies and network firewall rule groups set up in the region the clusters are hosted in.

This is the Terraform configuration I have set up for peering from my VPCs to the default VPC.

```
resource "aws_vpc_peering_connection" "default_to_environment" {
  count       = local.num_environment_vpcs
  peer_vpc_id = data.aws_vpc.environment[count.index].id
  auto_accept = true
  vpc_id      = var.vpc_default_id

  tags = {
    Name      = "Peer from default to ${data.aws_vpc.environment[count.index].tags["Name"]}"
    tf_module = "vpc"
  }
}

resource "aws_route_table" "r" {
  vpc_id = var.vpc_default_id

  # route = local.route_table_routes

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "igw-<number>"
  }

  dynamic route {
    for_each = [for r in local.route_table_routes : {
      cidr_block                = r.cidr_block
      vpc_peering_connection_id = r.vpc_peering_connection_id
    }]
    content {
      cidr_block                = route.value.cidr_block
      vpc_peering_connection_id = route.value.vpc_peering_connection_id
    }
  }

  tags = {
    Name = "default to environment VPCs"
  }
}

```

## Expected result

I expect `eks-cluster-broken` to be able to connect to the RDS cluster just like `eks-cluster-working` can.

## Question

What can cause this? Any suggestions as to how to go about debugging this?

# Answer
For my Peering Connection, I went to:

"Actions" -\> "Edit DNS Settings" -\> "Allow accepter VPC (`vpc-<id>`) to resolve DNS of requester VPC (vpc-`<id-default>`) hosts to private IP"

and checked it. (It was unchecked before). I had to wait a little while before this took effect.
> 4 votes

---
Tags: amazon-web-services, kubernetes, networking
---


title: Cheap alternative to Azure SQL database

text:
# Question
Title: Cheap alternative to Azure SQL database
I am building a system that processes articles from news websites and pushes the content to an analytics engine. The majority of the Azure cost from an SQL database.

This database is used to store a list of the urls to different websites. Each row is the name of the news source and the matching url link. If one wishes to add a news source, a new row is added manually. So the number of records is very little and stay like so when productionising, i.e. in alpha phase now, we have about 5 records, long term we may have 100-200 records maximum.

The bulk of the database cost comes from the read-write operations that happen frequently (every 15 seconds, all the rows are updated).

We feel like there should be a cheaper alternative Azure resource to store this little amount of data, rather than an expensive SQL database. A no SQL database somewhere, a simple JSON file that can be hosted somewhere on Azure, etc...?

What are your thoughts?

# Answer
You may be describing a key value store. It is unlikely that you need SQL or relational.

To avoid vendor-lock-in, and to control your costs. Avoid complex services from the cloud providers. Rent a machine or virtual machine from them, and put your own services on it. There are many Free and Open Source databases. Do some research: start with key-value stores (these are the simplest, fastest, but also low functionality, databases).
> 1 votes

# Answer
Why not spin up a virtual machine (ec2) and install a LAMP server on it.

MySQL server is free and the EC2 instance should be way cheaper than the SQL server.

(We do this on AWS; should work on Azure, too.)
> 0 votes

# Answer
If you want to keep with almost no code/syntax changes because adapting to another database engine, you can just boot a small VM with SQL Server 2019 Express edition on it.
> 0 votes

# Answer
You can use Storage Account Table.
> 0 votes

---
Tags: azure, cost-management
---


# Question
Title: Unable to run `conda activate` from Jenkins pipeline
I'm running Conda 4.6.14 on Ubuntu 16.04.

I thought about using virtual environments with Conda in my Jenkins pipelines that needed Ansible, by having all nodes use the same environment, `ansible-env` to run playbooks. While the process seems pretty straight forward, I'm unable to call `conda activate ansible-env`, because it results in the following error:

```
+ conda activate ansible-env

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'. To initialize your shell, run

    $ conda init <SHELL_NAME>

Currently supported shells are:
  - bash
  - fish
  - tcsh
  - xonsh
  - zsh
  - powershell

See 'conda init --help' for more information and options.

IMPORTANT: You may need to close and restart your shell after running 'conda init'.

```

Here is the code I'm using to activate...pretty basic

```
sh("conda activate ansible-env")
sh("ansible --version")
sh("conda deactivate")

```

I ran `conda init --system` on the build node as the Jenkins user and then rebooted. No change.

I've spent a great deal of time trying to google a solution, but everything I've tried hasn't worked.

**What I've attempted:**

* Tried running `sh("conda init bash")` in the pipeline.
* Executing `. /home/jenkins/miniconda3/profile.d/conda.sh` from within the pipeline.
* Made sure the `bin` directory for miniconda3 is set in $PATH.
* Ran `dpkg-configure dash` to make sure `/bin/bash` is the default shell on the node.
* Tried sourcing the `/home/jenkins/.bashrc` file
* Calling the `conda` executable via the absolute path.
* Tried using `source ansible-env` or `activate ansible-env` without `conda`.

I'm pretty sure the issue has to do with the following lines added to `~/.bashrc` of the jenkins user after running `conda init --system`, but still not being accessible from that same user when a job is running. Unfortunately, I've hit a wall and not sure where to go from here.

**NOTE:** Please don't suggest switching to VirtuanEnv unless there's a specific reason Conda won't work with Jenkins. I'm aware of that route, but went with conda for...reasons.

# Answer
> 2 votes
What we do is download and install miniconda in the first step in our (declarative) pipeline and create the environment(s) from a yaml file.

```
sh '''#!/usr/bin/env bash
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -nv -O miniconda.sh
bash miniconda.sh -b -p $WORKSPACE/miniconda
conda config --set always_yes yes --set changeps1 no
conda update -q conda

conda env create -f envs/ansible-env.yaml
'''

```

In each step we start the conda environment like so:

```
sh '''#!/usr/bin/env bash
source $WORKSPACE/miniconda/etc/profile.d/conda.sh
conda activate miniconda/envs/ansible-env/

# do stuff
'''

```

# Answer
> 1 votes
I've encountered the same issue when trying to use conda environments in CI builds and Docker images. The conda documentation does provide an example when using Travis CI, but it does not work for me.

However, via this blog I found a working solution! Instead of activating your environment, you can use it by calling `conda run -n my_env python my_file.py`. So, keep everything like it was until you activate your environment.

These build specs worked for me when using AWS CodeBuild:

```
{
  "version": "0.2",
  "phases": {
    "pre_build": {
      "commands": [
        "wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh -q",
        "bash miniconda.sh -b -p $HOME/miniconda",
        ". \"$HOME/miniconda/etc/profile.d/conda.sh\"",
        "hash -r",
        "conda config --set always_yes yes --set changeps1 no",
        "conda update -q conda",
        "conda info -a",
        "conda env create -q -p ./py_env -f environment.yml"
      ]
    },
    "build": {
      "commands": [
        "conda run -p ./py_env python app.py"
      ]
    }
  }
}

```

# Answer
> 0 votes
As a suggestion... Can you try calling the absolute path of the python executable in the environment? I mean: when you change conda environments, what happens is that the python executable you call changes path; you can find which python executable would be executed by

```
which python

```

Inside the environment. Then just forget about calling conda in the Jenkins pipeline. That should work if that’s what you’re changing environments for. Or are you changing the conda environment for some other reason?

EDIT: the same would happen when calling ansible as a library installed in the environment. It will change path to something like:

```
~/conda/envs/your_env/lib/ansible

```

---
Tags: jenkins
---


# Question
Title: Using a combination of Terraform and Ansible to create dynamic AWS EC2 infrastructure
The company I work for wants to prevent provider lock-in adn therefore told us to use Terraform+Ansible instead of Cloudformation. We already decided to use terragrunt as an addon. While the motivation for the company decision is clear they didn't provide guidance how to achieve this and we have to find out on our own how to do this in an "elegant" way.

In my scenario this means I use the two tools like this:

Terraform:

* provision EC2 instances (Ubuntu 20.04 in this case)
* define security groups with ingress rules
* define host name aliases (assigning them is a weak spot, I will come back to this later)

Ansible:

* install additional OS level components
* install and configure the application

All of this will be run from a devops machine, after that I have a working application setup. But what happens when for example monitoring decides that one of ten instances is no longer healthy ? That component will then be nuked and created from scratch. In this scenario, how can I make sure that:

* the replacement instance is configured using the same Ansible playbooks that were run before ?
* host name aliases will be updated

For the host name alias topic I have to give you a little bit more background on what we need. In one scenario we use an application that does not load balance. Because of this we create for example three instances which we assign aliases:

```
inst-one   -> lg1.company.foo
inst-two   -> lg2.company.foo
inst-three -> lg3.company.foo

```

Users access the instances using the aliases

Let's assume that `inst-two` becomes unhealthy, then this will need to happen:

```
inst-one   -> lg1.company.foo
inst-two   -> terminated
inst-new   -> lg2.company.foo
inst-three -> lg3.company.foo

```

# Answer
There are a lot of gaps in your deployment and configuration strategy. In order to provide a more robust and elegant strategy, I suggest you:

1. Define autoscaling groups with Terraform instead of provisioning individual EC2 instances. Auto-scaling groups make dynamically scaling instances a much simpler process. It will also allow you to define scaling policies and health checks for your instances to determine when to add/remove instances from your autoscaling group.
2. Create and define CloudWatch Metrics and CloudWatch Alarms. CloudWatch allows you to create custom metrics to monitor and alert via CloudWatch Alarms. This can be used in conjunction with autoscaling group scaling policies to define a threshold to scale your instances based on metrics such as cpu utilization, application response time, etc.
3. Instead of using Ansible to configure each EC2 instance, use Ansible to configure an Amazon Machine Image (AMI) to be uploaded and used by your autoscaling group. If your instances are configured identically, configuration is a one and done process. If your instances are configured differently, consider uploading multiple AMIs, and separating into multiple autoscaling groups. You can also use the User Data definition of an EC2 instance to run shell commands on each individual instance at **launch** (a one time process).
4. Last, but not least, instead of running this process from "a devops machine", consider using a build/deploy CI pipeline to run and configure this entire process. Tools such as AWS CodePipeline, Jenkins, GitLab CI, etc. allow for you and other team members to run your configuration in a configured and repeatable manner. It will also allow you define stages and deployment strategies should you choose to implement testing for your application later on in your development process.
> 3 votes

---
Tags: ansible, terraform, amazon-ec2
---


# Question
Title: In k8s, do the controller nodes have to be in same VPC as the worker nodes for a cluster?
I'm new to k8s and trying to grasp the infrastructure concepts, and trying to apply them in AWS. I know a k8s cluster has a control plane, which has the management nodes, and a data plane, which has the worker nodes. Do they have to run on their own respective VPC, or can they run on the same VPC? I hope that makes sense.

# Answer
> 1 votes
For Amazon EKS, the control plane is running in a separate VPC that is managed by Amazon. You only need to care about the VPC for the worker nodes.

> **Amazon EKS control plane** – Deployed and managed by Amazon EKS in an Amazon EKS managed VPC. When you create the cluster, Amazon EKS creates and manages network interfaces in your account that have Amazon EKS in their description. These network interfaces allow AWS Fargate and Amazon EC2 instances to communicate with the control plane.

From Amazon EKS Networking

---
Tags: amazon-web-services, kubernetes, eks
---


# Question
Title: How can I issue a Let's Encrypt certificate with Ansible when 'challenge_data' cannot be found?
I am attempting to use the Ansible `acme_certificate` module to acquire a Let's Encrypt TLS certificate.

I have successfully generated the private keys, CSRs, etc, and then started the challenge using the following task:

```
- name: Start challenge
  acme_certificate:
    acme_version: 1
    account_key_src: /etc/letsencrypt/account/account.key
    challenge: http-01
    csr: /etc/letsencrypt/csrs/{{ item }}.csr
    dest: /etc/letsencrypt/certs/{{ item }}.crt
    fullchain_dest: /etc/letsencrypt/certs/fullchain_{{ item }}.crt
  with_items:
  - www.example.com
  register: acme_challenge

```

I then attempt to satisfy the `http-01` challenge using:

```
- name: Implement challenge
  copy:
    content: "{{ acme_challenge['results']['challenge_data']['www.example.com']['http-01']['resource-value'] }}"
    dest: "/var/www/html/{{ acme_challenge['results']['challenge_data']['www.example.com']['http-01']['resource'] }}"
    owner: root
    group: root
    mode: u=rw,g=r,o=r

```

However, this results in the following error:

`The error was: 'list object' has no attribute 'challenge_data'`

I have tried accessing the `acme_challenge` variable in different ways, for example using `{{ acme_challenge.challenge_data['www.example.com']['http-01']['resource'] }}`, as well of various other combinations of square brackets and dots.

I've also copied the example of accessing the variable directly from the Ansible documentation, here and here, but that gives the same error.

After around 3 hours of trying I cannot read the challenge data at all. I've used a `debug` statement and I can confirm that it's all there properly, I just can't read the variable with this syntax.

Is this a known problem, or does anybody have a suggestion?

# Answer
> 1 votes
This was caused by the fact that I was starting the Let's Encrypt challenges using a `with_items` loop. From here:

> When using register with a loop, the data structure placed in the variable during the loop will contain a results attribute, that is a list of all responses from the module. For a more in-depth example of how this works, see the Loops section on using register with a loop.

The solution is to have a separate task for each Let's Encrypt challenge, rather than having them all in one.

# Answer
> 1 votes
For those searching, I found this post while experiencing the same issue. I was able to resolve this by adding the array index to my loop:

```
  copy:
    content: "{{ acme_challenge_your_domain['results'][ansible_loop.index0]['challenge_data'][item.hostname]['http-01']['resource_value'] }}"
    dest: "/var/www/{{ item.hostname }}/{{ acme_challenge_your_domain['results'][ansible_loop.index0]['challenge_data'][item.hostname]['http-01']['resource'] }}"
    owner: root
    group: root
    mode: u=rw,g=r,o=r
  loop: "{{ hosted_sites }}"
  loop_control:
    loop_var: item
    extended: yes

```

The specific changes here being converting with\_items to a loop and adding the loop\_control parameter extended. This allows for usage of ansible\_loop.index0.

---
Tags: ansible
---


title: Ansible: register variable with loop

text:
# Question
Title: Ansible: register variable with loop
What’s the best way to use registered variable ‘audit\_tools’ to check if all items are own by root ? Do I need to use Jinja2 filter or something ?

Thanks

```
- name: Verify audit tools are own by root user.
  block:
    - name: check if audit tools are own by root user.
      become: true
      stat:
        path: "/sbin/{{ audit_loop }}"
      loop:
        - auditctl
        - aureport
        - ausearch
        - autrace
        - auditd
        - audispd
        - augenrules
      loop_control:
        loop_var: audit_loop
      register: audit_tools

    debug:
      msg: “one or more tools are not own by root.”
    When: .....

  Rescue
     ......

```

# Answer
Q: **"*Check if all items are own by root.*"**

A: Put the list of the tools into the variable *audit\_tools*. Compare the length of the lists. For example

```
- hosts: localhost
  vars:
    audit_tools:
      - auditctl
      - aureport
      - ausearch
      - autrace
      - auditd
      - audispd
      - augenrules
  tasks:
    - block:
        - stat:
            path: "/sbin/{{ item }}"
          loop: "{{ audit_tools }}"
          register: result
        - assert:
            that: no_audit_tools == no_owner_root
            fail_msg: "One or more tools are not own by root."
          vars:
            no_audit_tools: "{{ audit_tools|length }}"
            no_owner_root: "{{ result.results|
                               json_query('[?stat.pw_name==`root`]')|
                               length }}"
      rescue:
        - debug:
            msg: "Rescue: audit tools not owned by root."

```

If not all items are owned by root *assert* will fail and the *block* will proceed to the *rescue* section

```
TASK [assert] ****
fatal: [localhost]: FAILED! => changed=false
  assertion: no_audit_tools == no_owner_root
  evaluated_to: false
  msg: One or more tools are not own by root.

TASK [debug] ****
ok: [localhost] =>
  msg: 'Rescue: audit tools not owned by root.'

```

---

Q: **"*This solution requires JMESPath to be installed. Is there an alternative solution?*"**

A: Yes. It is. Use Jinja filter selectattr

```
            no_owner_root: "{{ result.results|
                               selectattr('stat.pw_name', 'eq', 'root')|
                               list|length }}"

```
> 6 votes

---
Tags: ansible, linux, cicd
---


# Question
Title: Use a volume or copy my artefacts into docker image
I want to dockerize my php application and deploy it in production. Here is my application structure :

```
api
|
+-- src
+-- config
+-- vendor
+-- tests
+-- public

```

I need to embed `api/*` in my container, and I'm confused about the best approach. Here is mine :

1. A light multi-stage docker image (around 85 mb but can be more optimized)

```
FROM php:7.4-fpm-alpine AS base

WORKDIR /var/www/html
ENV COMPOSER_ALLOW_SUPERUSER 1
RUN apk update && \
  docker-php-ext-install mysqli tokenizer pdo_mysql && \
  curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

FROM base AS dev

COPY xdebug.ini /usr/local/etc/php/conf.d/xdebug-dev.ini
RUN apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS && \
  pecl install xdebug-2.9.1 && \
  docker-php-ext-enable xdebug && \
  touch /tmp/xdebug.log && \
  chmod -R 666 /tmp/xdebug.log && \
  apk del -f .phpize-deps

```
2. A mounted volume (docker-compose.yml)

```
api:
  volumes:
    - ./api:/var/www/html
  command: composer install && php-fpm;

```

I saw a lot of docker images using `COPY ..` instruction in `Dockerfile` instead of volumes. I believe `COPY` is great to copy small config files (or a small build for compiled languages), but it's not optimized to keep the images small (basic rule with docker).

Am I missing something? For example, is it bad practice to handle volumes from outside the dev environment ?

# Answer
Standard practice in non-development environments is to `COPY` the application code into the image, and to set the standard `CMD` there too.

```
...
COPY . .
RUN composer install
# php:fpm-alpine image already provides the correct CMD

```

There are a couple of important advantages to doing this:

* You can just run the Docker image directly on the target system; you don't have to copy the Docker image, and also the application code separately.
* `RUN composer install` happens only once during the build sequence. `command: composer install ...` runs on every restart, which is slower, uses network bandwidth, and can fail.
* If you give a unique tag to each image, you can easily roll back to an earlier image by changing the tag back. It's hard to do this with a volume mount.
* You'll `docker run` an identical image in all environments; you don't need to worry that the host-directory copy of the application is slightly different on that one system.

There's no specific rule that a Docker image needs to be very small; the only practical issue I've encountered is that multi-gigabyte images don't transfer across the network well. Indeed, I'd recommend the opposite choice around `COPY` vs. volumes that you've suggested: `COPY` the application code in, and use volumes for config files and other things that aren't "your code", and that need to be directly accessed from the host. (You do want to rebuild your application when the application changes; you don't want to rebuild your application when the database URL changes.)
> 2 votes

# Answer
To copy into the image or to mount volumes--my advice:

* if the files will change infrequently, then copy them into the image, with the understanding that if they need to be modified, you will need to rebuild the image.
* if you need to frequently change the files, or store some kind of state about the files (and re-use them with future container instances of the image), then mount them as volumes.
> 3 votes

---
Tags: docker, docker-compose
---


# Question
Title: Import data from SharePoint to Azure DevOps
We have migrated to DevOps from SharePoint 2010. We need to Import all the user stories we have in sharepoint to Azure DevOps . Can any one help me with a better way to go about this?

Know someone who can answer?

# Answer
> 2 votes
There are no tools to import data from SharePoint to Azure DevOps. You can consider the following:

1. Export SharePoint List to csv and then import it to Azure DevOps
2. Use Excel integration. Export Sharepoint list to Excel and then copy/paste data to Excel linked with Azure DevOps and publish it.

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


# Question
Title: Ansible No such file or directory error message for any executable in Amazon Linux AMI
I'm trying to run this command in a Amazon Linux AMI instance

```
  - name: Run docker
    shell: systemctl enable docker && systemctl start docker

```

And receiving this error message

```
"stderr": "/bin/sh: systemctl: No such file or directory"

```

I already tried with `command`, ansible systemd module and `/usr/bin/systemctl`.

# Answer
After struggling for a time I solved the problem by changing the image in the ci from Ubuntu to ansible-runner.
> 1 votes

---
Tags: ansible, amazon-ec2, linux
---


# Question
Title: Terraform - gitlab provider does not start
I am using terraform docker image `hashicorp/terraform:latest` and I define the provider in main.tf as follows:

```

terraform {
  required_providers {
    gitlab = {
      source = "gitlabhq/gitlab"
      version = "3.3.0"
    }
  }
}

provider "gitlab" {
    token = var.gitlab_token
}

```

When I run terraform apply, I get the following error:

```
Initializing provider plugins...
- Finding gitlabhq/gitlab versions matching "3.3.0"...
- Finding latest version of hashicorp/aws...
- Finding latest version of hashicorp/gitlab...
- Installing gitlabhq/gitlab v3.3.0...
- Installed gitlabhq/gitlab v3.3.0 (signed by a HashiCorp partner, key ID BC097C3333027B14)
- Installing hashicorp/aws v3.22.0...
- Installed hashicorp/aws v3.22.0 (signed by HashiCorp)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/plugins/signing.html
Error: Failed to query available provider packages
Could not retrieve the list of available versions for provider
hashicorp/gitlab: provider registry registry.terraform.io does not have a
provider named registry.terraform.io/hashicorp/gitlab
If you have just upgraded directly from Terraform v0.12 to Terraform v0.14
then please upgrade to Terraform v0.13 first and follow the upgrade guide for
that release, which might help you address this problem.
Did you intend to use gitlabhq/gitlab? If so, you must specify that source
address in each module which requires that provider. To see which modules are
currently depending on hashicorp/gitlab, run the following command:
    terraform providers

```

I can't find the solution to this issue from the documentation. Any suggestions?

terraform --version Terraform v0.14.3

# Answer
GitHub is one of the providers not yet included in the Terraform registry \- see this diff to the documentation. This appears to be a temporary situation:

> The following providers will be published on the Terraform Registry soon, but aren't quite ready. Until they're published, their documentation is available at the links below:

I can't tell from the release notes whether this is only in 0.14.x, but I can confirm that the "old" (*i.e.* current at the time of writing) github provider works with 0.12.x
> 1 votes

---
Tags: terraform, gitlab
---


title: ECK - Install Plugins: Error privileges

text:
# Question
Title: ECK - Install Plugins: Error privileges
**My *setup***:

### AWS EKS

```
* Platform: eks.3
* K8s: 1.18

```

### ECK (Elastic Cloud Kubernetes):

```
* Deployment via: Operator
* Elasticsearch version: 7.10.1

```

**Summary**

I'm trying to install the `repository-s3` plugin at Elasticsearch *pod*.

Here's my `YAML`:

```
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: elastic-test
spec:
  version: 7.10.1
  http:
    tls:
      selfSignedCertificate:
        disabled: true
  nodeSets:
  - name: default
    count: 1
    config:
      node.store.allow_mmap: false
    podTemplate:
      metadata:
        annotations:
          traffic.sidecar.istio.io/includeInboundPorts: "*"
          traffic.sidecar.istio.io/excludeOutboundPorts: "9300,443"
          traffic.sidecar.istio.io/excludeInboundPorts: "9300"
      spec:
        automountServiceAccountToken: true
        initContainers:
          - name: install-plugins
            securityContext:
              privileged: true
            command: ['sh', '-c', 'bin/elasticsearch-plugin install --batch repository-s3']

```

And when I'm *applying* the deployment crashes:

```
Exception in thread "main" org.elasticsearch.bootstrap.BootstrapException: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/config/repository-s3
Likely root cause: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/config/repository-s3
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixFileSystemProvider.newDirectoryStream(UnixFileSystemProvider.java:431)
    at java.base/java.nio.file.Files.newDirectoryStream(Files.java:476)
    at java.base/java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:300)
    at java.base/java.nio.file.FileTreeWalker.next(FileTreeWalker.java:373)
    at java.base/java.nio.file.Files.walkFileTree(Files.java:2840)
    at org.elasticsearch.common.logging.LogConfigurator.configure(LogConfigurator.java:220)
    at org.elasticsearch.common.logging.LogConfigurator.configure(LogConfigurator.java:129)
    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:354)
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170)
    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:161)
    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)
    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:127)
    at org.elasticsearch.cli.Command.main(Command.java:90)
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:126)
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)
For complete error details, refer to the log at /usr/share/elasticsearch/logs/elastic-test.log

```

Has someone managed to get around this?

# Answer
I discovered that it's a know *bug* of Elasticsearch version (7.10.x), after look this *issue* and I set to the version `7.9.3` and works fine!
> 1 votes

---
Tags: kubernetes, elasticsearch
---


title: Azure Devops x On-Premises

text:
# Question
Title: Azure Devops x On-Premises
Do I need to allow Azure DevOps access to the On-Premises environment? According to the document at "https://docs.microsoft.com/en-us/azure/devops/organizations/security/allow-list-ip-url? view = azure-devops, " on "Inbound connections" connections are made from the 191.235.226.0/24 (Brazil South) network, but we are receiving connections to our IPs 40.65.126.175, 40.117.36.92 and 52.152.147.38.

And the IPs are changed with each access making it impossible to restrict access.

Know someone who can answer?

# Answer
What are you trying to achieve? If your goal is to run build agents to execute pipelines on premises, then you don't have to allow inbound access. Build agents will query Azure DevOps for any new jobs, so the connections are actually outbound.
> 1 votes

---
Tags: azure, firewall
---


title: Is CaaS a thing?

text:
# Question
Title: Is CaaS a thing?
I often come across charts of application hosting models with a sorting similar to this one:

Dedicated → IaaS → CaaS → FaaS → PaaS → SaaS

* IaaS as machine + operating system
* FaaS as machine + operating system + servers
* PaaS as machine + operating system + servers + extra tools
* SaaS as machine + operating system + servers + extra tools + application/s

These are quite well defined concepts, but a "container" can contain each one of these (besides a non virtual machine); in other words, a container can start with an entire (virtual) machine and end where the sysadmin chooses to delineate it; hence I ask, **is CaaS a thing?**;
Is it well defined in comparison to other common hosting model categories?

# Answer
You have Azure Container Instances which is not even similar to Google Cloud Run. You can have a GCE instance running a single container. You can run containers in PaaS platforms like Azure App Service and AppEngine Flexible while this add you these extra tools like SSL, load balancing, CDN etc. AWS has their own ECS, AWS Fargate and Beanstalk.

The container deployment in a serverless model (Azure Container Instances/Google Cloud Run/AWS Fargate) seems useful, however, it is not standardised beyond container format. Most of the time it is for running a single container when you don't need all the bells and whistles of a PaaS, running a tool or a short batch job. ACI and Fargate can serve long running containers, Cloud Run is more like FaaS for containers.

For any more demanding solution Kubernetes definitely is a thing. Requires a little more understanding and configuration but every cloud provider has Kubernetes as a service. You can treat it as a standard.

Hard to say which one is CaaS...
> 0 votes

# Answer
**TL;DR**

Yes, CaaS is very much a thing it means Container-Orchestration-as-a-Service. Kubernetes is the leading technology in this space.

**Long Version**

The key to understanding the following progression is the concept of "-as-a-Service":

Dedicated → IaaS → CaaS → FaaS → PaaS → SaaS

It means you are paying either an internal or external team money to host a service onto which you deploy your business solution. Yes, you can use containers on top of a dedicated hardware service. You can use containers on-top of IaaS. Yet you have to look after the low-level concerns such as installing and patching the operating system. If you are simply renting VMs from a cloud provider you are not renting a container solution as a service.

When people talk about CaaS they usually mean “Container-Orchestration-as-a-service”. Examples include Amazon Elastic Kubernetes Service, Azure Kubernetes Service, and Google Kubernetes Engine, IBM Cloud Kubernetes Service and Alibaba Container Service for Kubernetes. There is a vast difference between deploying software onto a Kubernetes cluster that someone else set up, secured, then automated for you and having to configure a bunch of IaaS VMs to reliably run containers yourself. High-performance Kubernetes installations use specialist 'single purpose' operating systems such that the servers are more like appliances than typical VMs. The idea is that the cluster (both OS and Kubernetes software) can be security patched as a rolling upgrade without any downtime of the services hosted on the cluster.

**History Lesson ;-)**

The historic position around 2011 before Docker was released in 2013 would have been:

Dedicated → IaaS → PaaS → SaaS

In that, it is PaaS which, IMHO, is the vague classification that has changed over time with the rise of containers. Examples of early PaaS solutions that came before containers are the original Heroku, the original CloudFoundry, and early versions of RedHat Openshift. They were “DevOps platforms” before the term DevOps was invented. The original versions used some of the Linux techniques that containers later made famous, but it was an internal detail. The main marketing points made were two-fold. The first was developer productivity of having built-in CI/CD and the second was that the servers were easy to security patch and administer. The servers were treated like sheep and the vendor-supplied service packs to keep them secure.

The problems with the original PaaS concept was no standardisation, vendor lock-in, little portability, as well as proprietary tooling. They had embedded and proprietary build systems as well as proprietary configuration and deployment mechanisms. Opensource container orchestrators have revolutionised things by fixing those problems. The big open-source PaaS solutions such as OpenShift, CloudFoundry and Mesosphere now all support Kubernetes. Users no longer need to use a proprietary build and deploy pipeline nor propriety configuration mechanisms. They can use a vast number of different tools to build containers that they pushed up to any number of hosted container registries. They can then use the Kubernetes API to deploy into their chosen cloud provider. IMHO the original PaaS concept of “rapidly build, deploy and configure a web app” has standardised into CaaS as the main runtime.

**More info**:

if you want to see what you can do with CaaS checkout my blog on full automation of a start up.

**Update:**

I found the talks Stop Calling Knative Serverless! - Doug Davis very informative. At around 2:45 which compares PaaS, with CaaS, with FaaS. The talk introduces KNative and at the end around 32:07 compares KNative to PaaS, CaaS and FaaS. The presentation states that the Kubernetes definition of CaaS is rather bare-bones and missing a lot of "obvious" things if you are familiar with a PaaS. Both KNative and OKD (Openshift) are demonstrating that you can build another style of platform (PaaS, FaaS) on top of the bare-bones Kubernetes CaaS.
> 4 votes

---
Tags: culture, operating-model
---


# Question
Title: Secure way of uploading data to Google Cloud Storage
We're making some machines in which there's a part which uploads the images captured by the camera to Google Cloud Storage. For this purpose what I've done is

1. Create a service account for each machine.
2. Create a custom role with permissions:

> ```
> storage.objects.create
> storage.buckets.get
> storage.objects.get
>
> ```

3. Apply this role to that service account.
4. Download the JSON credentials key file and use this file with python script (in which I specify bucket name) to upload image to GCP Storage.

Is this way of doing things efficient and secure given that we only ship 2-3 machines each month?

Also I will have to ship JSON file with each machine, if the above method is valid, is this fine or there's any method to hide this key file?

# Answer
Yes, your approach sounds okay to me. I am not sure how you "ship" machines but it is a good idea to use a service account per machine as you can delete the service account key if the machine ever becomes compromised.

You can, and should, fully automate the process of generating the credentials key files using the Google APIs or gcloud cli.

It is best practice to periodically rotate (re-issue) credentials key files. This is in case they are accidentally leaked in a way that you do not notice. If you always revoke the key and issue a new one every month then it limits the total damage somewhat.

If you do rotate keys then you have a key distribution problem. How do you securely distribute the new credentials key files onto machines you shipped in the past? You can use GnuPG to create a public-private key pair on every host. Each month you can run a script that generates a new credentials key file per machine, encrypt it with the machine's public GPG key, then delete the old service account keys.

The script that pushes images to a bucket must then periodically "phone home" to collect a fresh GPG encrypted credentials key file. It can then decrypt it with its own private key. One way to do this is to put the encrypted keys into a different bucket. Create a single service account that can only read that bucket. Create a single credentials key file for that service account that you install onto every machine. That key can then only be used to only collect encrypted keys that can only be decrypted on the correct host.
> 1 votes

---
Tags: google-cloud-platform, google-cloud-storage
---


# Question
Title: Suggestions for a good run command review console
Is there a good web console or tool that would help enable us to review Shell Scripts?

Usually when maintaining a system, we would run scripts that are managed, or we could run scripts that run only once. However, these scripts must go through a vetting process to make sure they are secure, compliant, and won't create an issue.

We could of course create a git repo and create PR each time we want to run a script, but I am looking for a way for our members to submit scripts without fussing too much about format or folder structure.

# Answer
> I am looking for a way for our members to submit scripts without fussing too much about format or folder structure.

It sounds like you need some combination of testing and linting, perhaps with a few utility scripts to organise and gate content from landing in the repo.

The "Vetting process" you mention sounds to me exactly like "tests need to pass on the scripts". A widely-used framework to write such tests is the Bash Automated Testing System - BATS.

It would be up to you to write the tests to check whether, as you desire, these scripts are "secure, compliant and won't create an issue", but at least you have a framework for generating and running them.

At a more superficial level, you could use the Shellcheck linter to assert that any proposed new code adheres to whatever set of common rules you adopt in your community.

Pulling these together into a GitHub action (*e.g.* using https://github.com/github/super-linter), or a git pre-commit hook *etc* could be a good way to add a quick inspection to new contributions, and help maintainers.

These would provide quantitative measures of correctness. In order to also provide some qualitative or more subjective measures of acceptance, this would depend greatly on the operating environment and which tools would fit naturally into yours.

However, some tools do attempt to address this need by design. Without further knowledge of the environment it's difficult to provide concrete answers, but here is a comparison of two options:

## GitHub, GitLab requests

Assuming the code is destined for a GitHub or GitLab repo, GitHub or GitLab itself could of course be used as the "review console". A contributor would fork the repo, send a new contribution in the form of a PR against the repo, and then the checks referred to above would be executed.

The actions could take care of the organisation, based on some internal convention, *e.g.* using labels, *i.e.* "file scripts in PRs labelled `admin` in the `admin` directory".

## Gerrit

Another purpose-built tool to manage code contributions is Gerrit. Gerrit is heavily backed by git workflow and may not be relevant, but I mention it since it's one of the first such peer-review systems for software.

As described on the Gerrit website, a similar workflow is followed:

> Making the Change
>
> Creating the Review
>
> Reviewing the Change
>
> Reworking the Change
>
> Verifying the Change
>
> Submitting the Change
>
> Next Steps

Much of the actual work here is done by the reviewer or contributor, and Gerrit serves to organise their collaboration.

I suspect that neither of these corresponds exactly to what you are asking for, though, however a **general purpose** tool to which **arbitrary** contributions can be submitted is a big ask and likely a mirage.

It seems more feasible that this should be achieved by adopting shared conventions in existing code collaboration platforms rather than a dedicated service to manage ingestion.

---

Finally, you mention:

> Usually when maintaining a system...

If you meant "maintaining a configuration state of a system", perhaps an approach with Zuul. Zuul is

> ... a program that drives continuous integration, delivery, and deployment systems with a focus on project gating and interrelated projects.

While quite heavy, it is a means to actually execute and evaluate the result of a proposed script. This provides more meaningful feedback, but is of course more onerous in terms of setup and maintenance.
> 3 votes

---
Tags: shell-script, toolchain
---