I have setup an ECS Cluster and I'm using ECS CLI to create services/tasks from my existing docker-compose file.
This is how my compose file looks like:
version: "3"
services:
service-a:
image: 537403345265.dkr.ecr.us-west-1.amazonaws.com/service-a:latest
environment:
- SPRING_PROFILES_ACTIVE=dev
ports:
- "8100:8100"
service-b:
image: 537403345265.dkr.ecr.us-west-1.amazonaws.com/service-b:latest
environment:
- SPRING_PROFILES_ACTIVE=dev
- SERVICE_A_BASE=service-a:8100
ports:
- "8101:8101"
depends_on:
- service-a
and my ecs-params.yml:
version: 1
task_definition:
task_execution_role: ecsTaskExecutionRole
ecs_network_mode: awsvpc
os_family: Linux
task_size:
mem_limit: 2GB
cpu_limit: 256
run_params:
network_configuration:
awsvpc_configuration:
subnets:
- "subnet-xx"
- "subnet-xy"
security_groups:
- "sg-xz"
assign_public_ip: ENABLED
where I'm using SERVICE_A_BASEas the base URL for calling service A from Service B.
The same compose file works fine in my local but it is not working inside my ECS Cluster.
I have set inbound rules to allow ports 8100 and 8101 in my security group.
What might be wrong or Is there an another way of doing this?
I want to configure a Firewall and a Startup Script with Deployment Manager template in .yaml file
Below are the steps I need to perform
A new Deployment Manager deployment has been created
The deployment includes a virtual machine that has an embedded
startup-script
The virtual machine that has a startup-script also has a tag item
called http
A firewall rule exists that allows port 80 (http) traffic and is
applied using a tag with a value of http
The virtual machine responds to web requests using the Apache web
server
Check that Deployment manager includes startup script and firewall
resources
Below is the sample file i have created, but while deploying the file its showing that step 3 (The virtual machine that has a startup-script also has a tag item called http) was not configured.
Please help me if I missed any thing.
- name: my-vm
type: compute.v1.instance
properties:
zone: us-central1-a
machineType: zones/us-central1-a/machineTypes/n1-standard-1
sourceRanges: ["0.0.0.0/0"]
targetTags: ["webserver"]
allowed:
- IPProtocol: TCP
ports: ["80"]
metadata:
items:
- key: startup-script
value: |
#! /bin/bash
apt-get update
apt-get install -y apache2
cat <<EOF > /var/www/html/index.html
<html><body><h1>Welcome to Apache</h1>
<p>This page was created from a simple startup script!</p>
</body></html>
disks:
- deviceName: boot
type: PERSISTENT
boot: true
autoDelete: true
initializeParams:
sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-9-stretch-v20180814
networkInterfaces:
- network: https://www.googleapis.com/compute/v1/projects/qwiklabs-gcp-dee231a39b26c176/global/networks/default
accessConfigs:
- name: External NAT
type: ONE_TO_ONE_NAT
The option "value" should be a string format.
For example:
metadata:
items:
- key: startup-script
value: "apt-get update \n apt-get install -y apache2"
The virtual machine that has a startup-script also has a tag item called http) was not configured.
as it expresses that a tag item as http must be mentioned for your vm instance .
just mention a tags just after zone->machinetype in properties of the vm-instance
zone: your-zone
machineType: your-machine-type
tags:
items:
- 'http'
I am having trouble trying to deploy my Django Application and PostgreSQL database to Kubernetes Google Cloud cluster that I've already configured.
I have successfully created Docker containers for my Django Application and PostgreSQL database. Here is what my docker-compose.yml file looks like:
version: '3'
services:
db:
image: postgres
environment:
- POSTGRES_USER=stefan_radonjic
- POSTGRES_PASSWORD=cepajecar995
- POSTGRES_DB=agent_technologies_db
web:
build: .
command: python manage.py runserver 0.0.0.0:8000 --settings=agents.config.docker-settings
volumes:
- .:/agent-technologies
ports:
- "8000:8000"
links:
- db
depends_on:
- db
I have already build the images, and tried sudo docker-compose up command, and the application works perfectly fine.
After successfully dockerizing Django Application and PostgreSQL, I have tried to configure Deployment / Service YML files required by Kubernetes, but I am having trouble doing so. For example:
deployment-definition.yml - File for deploying Django application:
apiVersion: apps/v1
kind: Deployment
metadata:
name: agent-technologies-deployment
labels:
app: agent-technologies
tier: backend
spec:
template:
metadata:
name: agent-technologies-pod
labels:
app: agent-technologies
tier: backend
spec:
containers:
- name:
image:
ports:
- containerPort: 8000
replicas:
selector:
matchLabels:
tier: backend
Inside container list of dictionaries, I know that my container name should be web, but I am not sure where the image of that container is located so I do not know what should i specify as container image.
Another problem lies in postgres/deployment-definition.yml :
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 1
selector:
matchLabels:
app: postgres-container
template:
metadata:
labels:
app: postgres-container
tier: backend
spec:
containers:
- name: postgres-container
image: postgres:9.6.6
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-credentials
key: user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-credentials
key: password
- name: POSTGRES_DB
value: agent_technologies_db
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-volume-mount
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-volume-mount
persistentVolumeClaim:
claimName: postgres-pvc
I do not understand what volumeMounts and volumes are for, and if i even specified them correctly.
Here is my secret-definition.yml file:
apiVersion: v1
kind: Secret
metadata:
name: postgres-credentials
type: Opaque
data:
user: stefan_radonjic
passowrd: cepajecar995
My postgres/service-definition.yml file:
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app: postgres-container
ports:
- protocol: TCP
port: 5432
targetPort: 5432
My postgres/volume-definition.yml file:
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
labels:
type: local
spec:
capacity:
storage: 2Gi
storageClassName: standard
accessModes:
- ReadWriteMany
hostPath:
path: /data/postgres-pv
And my postgres/volume-claim-definitono.yml file:
apiVersion: v1
kind: PersistentVolume
metadata:
name: postgres-pv
labels:
type: local
spec:
capacity:
storage: 2Gi
storageClassName: standard
accessModes:
- ReadWriteMany
hostPath:
path: /data/postgres-pv
Last but not least, my service-definition.yml file - for Django application
apiVersion: v1
kind: Service
metadata:
name: agent-technologies-service
spec:
selector:
app: agent-technologies
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: NodePort
Besides the questions I have already asked above, I also want to ask am I doing this right? If not, what can I do to fix this.
Inside container list of dictionaries, I know that my container name should be web, but I am not sure where the image of that container is located so I do not know what should i specify as container image.
Name for container is local to the pod (you can have several containers sharing same pod). Container name (web in your case) is for your files given under deployment:
# setting name of first container within pod to web
spec:
containers:
- name: web
Image for container has to be in some available docker container registry. There are multiple options from hosting own docker registry to use publicly available ones. In any case you have to be able to push in your build phase to that docker container registry (be it amazon ECR, Docker, Gitlab, self hosted...) and to pull from that registry from within kubernetes (security settings, pull secrets etc...). In your docker-compose file you use two containers. For db you use public postgres image, and for web you use build command and image is stored to local docker registry on that host only (you have to push it to public repository for k8s to be able to pull from it during deployment).
I do not understand what volumeMounts and volumes are for, and if i even specified them correctly.
In a nutshell, volumes are for attaching volumes to containers. Depending on your use case and decided architecture there are several approaches to volumes, but all in all they boil down to ephemeral, constant and persistent. Ephemeral will be lost on container termination or restart, constant (such as from configMaps) are used for passing configuration files to containers and persistent are most interesting for stateful applications (databases among other things). You can specify volumes in several ways, all volume have to have name (to be referenced by volumeMount) and either direct volume specification or volume claim specification (latter is advised for persistent volume since you can benefit from automatic provisioning that way).
VolumeMounts are for defining where on container file system predefined volume should be mounted. They reference volume to be mounted by name, provide mount point on container filesystem by mountPath and can have subpaths to specific files in some cases.
In your example you tied persistent volume claim obtained volume to data path of postgres (/var/lib/postgresql/data). Althought you use storage class that you didn't specify, interesting part is that your Persistent volume is defined as localpath on host. That means that on each node you have this database pod started you will end up pointing /var/lib/postgresql/data of that pod's db container to /data/postgres-pv on that specific node. This opens up you to following issue: say you have 3 nodes (A, B and C) and your database pod is started on A, uses A's /data/postgres-pv folder as own /var/lib/postrgresql/data. And then you restart it, it gets terminated and rescheduled to node B. All of the sudden, it uses B's /data/postgres-pv local folder (empty) and you end up with empty database. If you use host's local filesystem for persisntence you need to tie such pods with node (or better yet with affinity) selectors. It is advisable for performance reasons to run database volumes of local filesystem, but hose pods lose ability to be rescheduled easily. Another approach is to have some truly persistent volume that can be mounted independently of node (Amazon EBS for example) and they require different PVC (or provisioner to be used).
Besides the questions I have already asked above, I also want to ask am I doing this right? If not, what can I do to fix this.
As stated above, define storage class and either lock db pod to specific node or apply some kind of dynamic provisioning so volume will follow pod's placement on nods.
Oppiniated preference: don't place everything in default namespace, use separate namespace for handling k8s manifests, later on it is much harder to move everything, and harder to accidentally delete wrong thingie...
Also personal preference: database is stateful application and as such it is advised to use statefulset instead of deployment.
There are tools to help you out when you start from docker-compose files and want to convert to kubernetes manifests, worth checking.
Documentation on kubernetes is a bit outdated but quite good and you can have some nice read on volumes and volumeClaims there, there is also active slack channel.
Oh, and mock user/pass when posting files here, we know now about cepa...
Lastly, you are doing great job!
I'm trying to use glusterfs installed directly on my GCE cluster nodes.
The installation does not persist through cluster upgrades, which could be solved with a bootstrap script.
The problem is that when I did reinstall the glusterfs manually and mounted the brick, there was no volumes present, which I had to force recreate.
What happened? Does glusterfs store volume data somewhere else than on bricks? How do I prevent this?
Can I confirm you are doing this on a Kubernetes cluster? I presume you are as you mentioned cluster upgrades.
If so, when you say gluster was installed directly on your nodes, I'm not sure I understand that part of your post. My understanding of the intended use of glusterfs is that it's exists as a distributed file system, and the storage is therefore part of a separate cluster to the Kubernetes nodes.
I believe this is the recommended method to use glusterfs with Kubernetes, and this way the data in the volumes will be retained after the Kubernetes cluster upgrade.
Here are the steps I performed.
I created the glusterfs cluster using the information/script from the first three steps in this this tutorial (specially the 'Clone' 'Bootstrap your Cluster' and 'Create your first volume' steps). In terms of the YAML below, It may be useful to know my glusterfs volume was named 'glustervolume'.
Once I'd confirmed the gluster volume had been created, I created Kubernetes and service and end points that point at that volume. The IP addresses in the the end point section of the YAML below are the internal IP addresses of the instances in the glusterfs storage cluster.
---
apiVersion: v1
kind: Service
metadata:
name: glusterfs-cluster
spec:
ports:
- port: 1
---
apiVersion: v1
kind: Endpoints
metadata:
name: glusterfs-cluster
subsets:
- addresses:
- ip: 10.132.0.6
ports:
- port: 1
- addresses:
- ip: 10.132.0.7
ports:
- port: 1
- addresses:
- ip: 10.132.0.8
ports:
- port: 1
I then created a pod to make use of the gluster volume:
---
apiVersion: v1
kind: Pod
metadata:
name: glusterfs
spec:
containers:
- name: glusterfs
image: nginx
volumeMounts:
- mountPath: "/mnt/glusterfs"
name: glustervolume
volumes:
- name: glustervolume
glusterfs:
endpoints: glusterfs-cluster
path: glustervolume
readOnly: false
As the glusterfs volume exists separately to the Kubernetes cluster (i.e. on it's own cluster), Kubernetes upgrades will not affect the volume.
I have a Kubernetes cluster running on Google Cloud Platform. I have 3 nodes and several pods running on these nodes.
One of the pods runs Ghost blog platform and has mounted a gcePersistentDisk volume. The manifest file to create the pod:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
name: ghost
name: ghost
spec:
replicas: 1
template:
metadata:
labels:
name: ghost
spec:
containers:
- image: ghost:0.7
name: ghost
env:
- name: NODE_ENV
value: production
ports:
- containerPort: 2368
name: http-server
volumeMounts:
- name: ghost
mountPath: /var/lib/ghost
volumes:
- name: ghost
gcePersistentDisk:
pdName: ghost
fsType: ext4
I'd like someway to access this volume from my development machine. Is there any way to mount this disk in my machine?
If your development machine is not part of the GCE cluster (i.e. a GCE VM), then you will not be able to directly mount it. Your best bet in that case would be to SSH to it via a machine it is mounted it (i.e the node your pod is scheduled to).