If I have a domain name www.domain.com registered and I have fresh kubernetes cluster up and running. I have successfully lauched Deployments and Services to expose the requirements.
The service is creating a LoadBalancer on my GCE cluster and when I try to access my APP through the the external IP its working.
But this is what I wanted to achieve ideally :
To route all the traffic for my apps as www.app.domain.com , www.app2.domain.com. Upon research I have found that I need an Ingress Controller preferably NGINX server, I have been try to do this and failing miserably.
This is the service exposing JSON for my deployments:
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": 'node-js-srv'
},
"spec": {
"type": 'LoadBalancer',
"label": {
'app': 'node-js-srv'
},
"ports": [
{
"targetPort": 8080,
"protocol": "TCP",
"port": 80,
"name": "http"
},
{
"protocol": "TCP",
"port": 443,
"name": "https",
"targetPort": 8080
}
],
"selector": {
"app": 'node-js'
},
}
}
GCE/GKE have already a Ingress Controller and you could use that one.
You must specify your service as type NodePortand create a ressource from type Ingress
See:
https://kubernetes.io/docs/user-guide/ingress/
You find a example for GCE here https://github.com/kubernetes/ingress/tree/master/examples/deployment/gce
Service:
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": 'node-js-srv'
},
"spec": {
"type": 'NodePort',
"label": {
'app': 'node-js-srv'
},
"ports": [
{
"targetPort": 8080,
"protocol": "TCP",
"port": 80,
"name": "http"
},
{
"protocol": "TCP",
"port": 443,
"name": "https",
"targetPort": 8080
}
],
"selector": {
"app": 'node-js'
},
}
}
Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: www.app.domain.com
http:
paths:
- backend:
serviceName: node-js-srv
servicePort: 80
- host: www.app2.domain.com
http:
paths:
- backend:
serviceName: xyz
servicePort: 80
Related
I am looking for a method to test the current provided hosting configuration for Firebase Hosting, the firebase.json file seems to deploy correctly, but there doesn't seem to be a way to see this configuration on the cloud once its deployed:
firebase.json
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "/api/v1/**",
"function": "webApp"
},
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{
"source": "**/*",
"headers": [
{
"key": "Cache-Control",
"value": "no-cache"
},
{
"key": "Content-Security-Policy",
"value": "frame-ancestors 'self' *://*.hellosign.com"
}
]
}
]
},
"emulators": {
"functions": {
"host": "0.0.0.0",
"port": 5001
},
"firestore": {
"host": "0.0.0.0",
"port": 8080
},
"database": {
"host": "0.0.0.0",
"port": 9000
},
"hosting": {
"host": "0.0.0.0",
"port": 5000
},
"pubsub": {
"host": "0.0.0.0",
"port": 8085
},
"auth": {
"host": "0.0.0.0",
"port": 9099
},
"ui": {
"enabled": true,
"host": "0.0.0.0",
"port": 4000
}
},
"firestore": {
"rules": "firestore.rules"
}
}
The documentation states:
You can check the deployed firebase.json content using the Hosting REST API.
You will need to use that API to check that your release matches your expectations. You won't be able to see this in the console. If console access what you're looking for, then file a feature request with Firebase support.
I have a reverse proxy server with NGINX and I want to test its configuration automatically.
What I want to achieve in the end is to have a command that I can run, it starts the NGINX with the configuration, run several http requests, and then track and gather whether the right proxied server was called.
I've been thinking on setting up an environment with docker-compose and use curl/wget with the list of urls I want to test. The thing that I don't know is how to mock certain domains and track the forwarded requests.
Is there a tool to do that or should I write a server manually?
After experimenting a bit I managed to create this solution.
Use Docker Compose, Wiremock and Newman. The idea is to setup NGINX proxying requests to Wiremock (where you can control if the request matched the right structure), then with Newman, you can run a Postman collection that automatically checks that the stubbed responses are the right ones.
Example
Create all these files in a folder, get the testing environment by running
docker-compose up -d nginx wiremock
and then, to run the test suite
docker-compose run --rm newman
It should print the results of the collection.
Files
docker-compose.yml
version: "3"
services:
nginx:
image: nginx
ports:
- "80:80"
volumes:
- ./config:/etc/nginx
wiremock:
image: wiremock/wiremock:2.32.0
command: [ "--port", "80", "--verbose" ]
ports:
- "8080:80"
volumes:
- ./wiremock:/home/wiremock
networks:
default:
aliases:
- backend-service-1
- backend-service-2
newman:
image: postman/newman
volumes:
- ./newman:/etc/newman
command: [ "run", "example.postman_collection.json" ]
config/nginx.conf
events {
worker_connections 1024;
}
http {
resolver 127.0.0.11; # docker internal resolver
server {
listen 80 default_server;
location /some/path/ {
proxy_set_header X-Forwarded-Host $host;
proxy_pass http://backend-service-1/some/path;
}
location /other/path/ {
proxy_set_header X-Forwarded-Host $host;
proxy_pass http://backend-service-2/other/path;
}
}
}
wiremock/mappings/some-path.json
{
"request": {
"method": "GET",
"url": "/some/path",
"headers": {
"Host": {
"equalTo": "backend-service-1",
"caseInsensitive": true
}
}
},
"response": {
"status": 200,
"body": "{\"host\": \"from-1\"}",
"headers": {
"Content-Type": "application/json"
}
}
}
wiremock/mappings/other-path.json
{
"request": {
"method": "GET",
"url": "/other/path",
"headers": {
"Host": {
"equalTo": "backend-service-2",
"caseInsensitive": true
}
}
},
"response": {
"status": 200,
"body": "{\"host\": \"from-2\"}",
"headers": {
"Content-Type": "application/json"
}
}
}
newman/example.postman_collection.json
{
"info": {
"name": "example",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "some path",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"request backend service 1\", function () {",
" pm.response.to.have.status(200);",
"",
" var jsonData = pm.response.json();",
" pm.expect(jsonData.host).to.eql(\"from-1\");",
"});",
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://nginx/some/path/",
"protocol": "http",
"host": [
"nginx"
],
"path": [
"some",
"path",
""
]
}
},
"response": []
},
{
"name": "other path",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"request backend service 2\", function () {",
" pm.response.to.have.status(200);",
"",
" var jsonData = pm.response.json();",
" pm.expect(jsonData.host).to.eql(\"from-2\");",
"});",
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://nginx/other/path/",
"protocol": "http",
"host": [
"nginx"
],
"path": [
"other",
"path",
""
]
}
},
"response": []
}
]
}
I already have the ElasticBeanstalk (Multicontainer) template. In addition to that, I want to get Docker image from ECR which I already have ****.dkr.ecr.ap-south-1.amazonaws.com/traveltouch:latest in my ECR repo. (If want to create new repo also fine). I mentioned that image in my Dockerrun.json and Dynamodb also needed. Here how to attach that permission and add My ECR repo and new dynamodb table into to my MyInstanceProfile and the cloudformation.
AWSTemplateFormatVersion: '2010-09-09'
Resources:
sampleApplication:
Type: AWS::ElasticBeanstalk::Application
Properties:
Description: AWS Elastic Beanstalk Sample Application
sampleApplicationVersion:
Type: AWS::ElasticBeanstalk::ApplicationVersion
Properties:
ApplicationName:
Ref: sampleApplication
Description: AWS ElasticBeanstalk Sample Application Version
SourceBundle:
S3Bucket: !Sub "elasticbeanstalk-ap-south-1-182107200133"
S3Key: TravelTouch/Dockerrun.aws.json
sampleConfigurationTemplate:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Properties:
ApplicationName:
Ref: sampleApplication
Description: AWS ElasticBeanstalk Sample Configuration Template
OptionSettings:
- Namespace: aws:autoscaling:asg
OptionName: MinSize
Value: '2'
- Namespace: aws:autoscaling:asg
OptionName: MaxSize
Value: '6'
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: LoadBalanced
- Namespace: aws:autoscaling:launchconfiguration
OptionName: IamInstanceProfile
Value: !Ref MyInstanceProfile
SolutionStackName: 64bit Amazon Linux 2018.03 v2.26.0 running Multi-container Docker 19.03.13-ce (Generic)
sampleEnvironment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
ApplicationName:
Ref: sampleApplication
Description: AWS ElasticBeanstalk Sample Environment
TemplateName:
Ref: sampleConfigurationTemplate
VersionLabel:
Ref: sampleApplicationVersion
MyInstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- sts:AssumeRole
Description: Beanstalk EC2 role
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier
- arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker
- arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier
MyInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref MyInstanceRole
and my Dockerrun.json
{
"AWSEBDockerrunVersion": 2,
"containerDefinitions": [{
"environment": [{
"name": "POSTGRES_USER",
"value": "admin"
},
{
"name": "POSTGRES_PASSWORD",
"value": "postgres"
},
{
"name": "POSTGRES_DB",
"value": "traveldb"
}
],
"essential": true,
"image": "postgres:12-alpine",
"memory": 300,
"mountPoints": [{
"containerPath": "/var/lib/postgresql/data/",
"sourceVolume": "postgres_data"
}],
"name": "db",
"portMappings": [{
"containerPort": 5432,
"hostPort": 5432
}]
},
{
"essential": true,
"links": [
"db"
],
"name": "web",
"image": "****.dkr.ecr.ap-south-1.amazonaws.com/traveltouch:latest",
"memory": 300,
"portMappings": [{
"containerPort": 80,
"hostPort": 80
}]
}
],
"volumes": [{
"host": {
"sourcePath": "postgres_data"
},
"name": "postgres_data"
}
]
}
I have two applications that handle different, but related functionality. I would like to deploy them as a single entity on a single host:port.
My plan is to use elasticbeanstalk's multicontainer docker platform. Each application would be a container.
How can I tie them together? Is it possible to install and configure nginx on the eb host?
You need to define all containers that comprise your application (together with nginx container) in Dockerrun.aws.json.
{
"AWSEBDockerrunVersion": 2,
"volumes": [
{
"name": "nginx-proxy-conf",
"host": {
"sourcePath": "/var/app/current/conf.d"
}
}
],
"containerDefinitions": [
{
"name": "first-app",
"image": "FIRST_APP_IMAGE_NAME:FIRST_APP_TAG",
"environment": [],
"essential": true,
"memoryReservation": 200,
"mountPoints": [],
"portMappings": [
{
"hostPort": 8081,
"containerPort": 8080
}
]
},
{
"name": "secondapp",
"image": "SECOND_APP_IMAGE_NAME:SECOND_APP_TAG",
"environment": [],
"essential": true,
"memoryReservation": 200,
"mountPoints": [],
"portMappings": [
{
"hostPort": 8082,
"containerPort": 8080
}
]
}
{
"name": "nginx-proxy",
"image": "nginx",
"essential": true,
"memoryReservation": 128,
"portMappings": [
{
"hostPort": 80,
"containerPort": 80
}
],
"links": [
"firstapp", "secondapp"
],
"mountPoints": [
{
"sourceVolume": "nginx-proxy-conf",
"containerPath": "/etc/nginx/conf.d",
"readOnly": true
}
]
}
]
}
Now as we linked app containers to nginx container we can refer to them using their names as hostnames.
And then you need to deploy Dockerrun.aws.json zipped together with nginx config conf.d/default.conf file (put into conf.d folder) in which you need to specify
location /firstapp/ {
proxy_pass http://firstapp;
}
location /secondapp/ {
proxy_pass http://secondapp;
}
Please also refer to AWS example of nginx proxy before php application.
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_v2config.html
When I create a Kubernetes Load Balancer Service using the following specification:
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "a1"
},
"spec": {
"selector": {
"app": "a1"
},
"ports": [
{
"port": 80,
"targetPort": 80,
"name": "http"
},
{
"port": 443,
"targetPort": 443,
"name": "https"
}
],
"type": "LoadBalancer"
}
}
I have to wait between 1 and 2 minutes until I get an EXTERNAL_IP.
I thought of reserving static IPs before and assigning them on Service creation:
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "a1"
},
"spec": {
"selector": {
"app": "a1"
},
"ports": [
{
"port": 80,
"targetPort": 80,
"name": "http"
},
{
"port": 443,
"targetPort": 443,
"name": "https"
}
],
"type": "LoadBalancer",
"loadBalancerIP": "130.211.64.237"
}
}
But I have the same delay 1 - 1.5 minutes:
$ kubectl get svc
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
a1 10.127.248.248 130.211.64.237 80/TCP,443/TCP app=a1 1m
Does anyone know why this delay happens and if there is a way to shorten it?
The delay is unfortunately just caused by latency in the Compute Engine APIs for creating the components of a load balanced service, and there's no real way to avoid it.
The Kubernetes master, when instructed to create a load balancer, has to create a static IP address, a target pool, a forwarding rule, and a firewall rule. These resources can take some time to fully initialize and be ready for use, so a wait of a minute or two is to be expected for now.