Создаю AWS Route53 CNAME, что-то типа такого:
docker-ecr.internal.vnatarov.io -> XXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com
Выглядит это так:

Если вы выполните авторизацию по созданному CNAME, то получите ошибку:
$ CNAME_URL="docker-ecr.internal.vnatarov.io" &&\
aws ecr get-login-password --region us-east-1 --profile default | docker login --username AWS --password-stdin $CNAME_URL
Error response from daemon: Get "https://docker-ecr.internal.vnatarov.io/v2/": x509: certificate is valid for *.dkr.ecr.us-east-1.amazonaws.com, *.dkr.ecr.us-east-1.vpce.amazonaws.com, not docker-ecr.internal.vnatarov.io
Т.е нельзя использовать CNAME т.к Амазон подписал AWS ECR домен своим сертификатом. Окай…. Не логично, но ладно! Я думал все у Амазан будет интуитивно легко и просто — нет.
Подумав немного, придумал пару решений:
Приступим!
Покопавшись в REST API Amazon (boto3), я увидел что можно подложить хеадеры и выполнить авторизацию и получить репозитории с AWS ECR. Сразу решил проверить, например вот так:
$ CNAME_URL="https://docker-ecr.internal.vnatarov.io" &&\
AWS_ACCOUNT_ID="XXXXXXXXXXXXXXX" &&\
AWS_ECR_REPO_NAME="repo-name" &&\
TOKEN=$(aws ecr get-authorization-token --region us-east-1 --profile default --output text --query 'authorizationData[].authorizationToken') && curl -k -i -H "Host: $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com" -H "Authorization: Basic $TOKEN" -H "X-Forwarded-Proto: https" -H "X-Forwarded-For 127.0.0.1" -H "X-Real-IP: 93.72.109.140" $CNAME_URL/v2/$AWS_ECR_REPO_NAME/tags/list
Вывод команды:
HTTP/1.1 200 OK
Docker-Distribution-Api-Version: registry/2.0
Link: <https://XXXXXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/v2/repo-name/tags/list?last=ukD72mdD%2FmC8b5xV3susmJzzaTgp3hKwR9nRUW1yZZ7uIM42T5Qni9DYGx4CJpnhNeJ6HnjEzAukCdhHEgsIYR6ZPbIPWoMte%2Bkmss2BWER%2BOoldEmVa6n9tG88nfx8J3qz2X7nNmzKTvj9S75hqjlupun8iXyGm2Cef6EHKr6JqI7jXVAS0aBWToKUCsATn1R2LRKTxsdsk7HLTSmjieo3kdVioZ6%2F0%2BsiGagwFc6QZfrwH1%2Bl%2F%2Ba1ritf4IwZUXVC4kuID%2BzHKxz9rtgMBgDDBA1yjW8hZqO3K2tOa77h3i%2BPVqj6aHA096YMRh5BFiiLWPGgss0L4QQahaooOLRRg7kdr5k%2FZIqllcmGaLbioNLy3R5jOon7X61YbIGF7fUOkssj72o37fpPd%2FJG2g%3D%3D>; rel="next"
Date: Wed, 17 Nov 2021 11:06:47 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
{"name":"repo-name","tags":["943bf60acceb327ee85717d2b52cfd97374f4340","ade31de1df53b7c96575f6f27bec17c9f7702cb8"]}
С вывода команды можно понять что подложив хеадеры, можно получить репы. Пишем питон-скрипт…. Потребовалось часов 12 на написания данного скрипта и он довольно стабилен в работе.
Установкой Питон и pip я не буду. Но если нет в систему — ставим. А тем временем, нужно установить следующие пакеты:
# A Fast, Extensible Progress Bar for Python and CLI
tqdm==4.62.3
# AWS
boto3~=1.19.3
botocore~=1.22.3
# Others
setuptools~=57.4.0
urllib3~=1.22
Python скрипт выглядит:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import json
import logging
import os
import shutil
import tarfile
import time
import urllib
from tempfile import mkdtemp
import boto3
import botocore
import botocore.session
import urllib3
from botocore.config import Config
# Initialize Logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logging.captureWarnings(True)
CACHE_DIR_ROOT = os.path.expanduser("~")
assert os.path.isdir(CACHE_DIR_ROOT)
CACHE_DIR = CACHE_DIR_ROOT + '/.docker-pull-layers-cache/'
if not os.path.exists(CACHE_DIR):
print("Creating cache directory: " + CACHE_DIR)
os.makedirs(CACHE_DIR)
def ec2_connector(aws_settings):
if (aws_settings['client'] is not None) and (aws_settings['region'] is not None):
try:
session = botocore.session.get_session()
access_key = session.get_credentials().access_key
secret_key = session.get_credentials().secret_key
session_token = session.get_credentials().token
session = boto3.session.Session()
ec2 = session.client(aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
aws_session_token=session_token,
service_name=aws_settings['client'],
region_name=aws_settings['region'],
config=Config(retries={'max_attempts': 3})
)
return ec2
except Exception as err:
print("Failed to create a boto3 client connection to ecr:\n", str(err))
logger.error('ERROR: Failed to create a boto3 client connection')
return False
else:
print('Please use/set [--bclient] and [--region]')
return False
def ecr_connector(aws_settings):
if (aws_settings['role_name'] is None or aws_settings['role_name'] == "None") \
and (aws_settings['role_session'] is None or aws_settings['role_session'] == "None"):
try:
session = boto3.session.Session(profile_name=aws_settings['profile_name'])
# Will retry any method call at most 3 time(s)
ecr = session.client(service_name=aws_settings['client'],
region_name=aws_settings['region'],
config=Config(retries={'max_attempts': 3})
)
return ecr
except Exception as err:
print("Failed to create a boto3 client connection to ecr:\n", str(err))
logger.error('ERROR: Failed to create a boto3 client connection to ecr')
return False
elif (aws_settings['profile_name'] is None or aws_settings['profile_name'] == "None") \
and (aws_settings['role_name'] is not None or aws_settings['role_name'] != "None") \
and (aws_settings['role_session'] is not None or aws_settings['role_session'] != "None"):
try:
session = boto3.session.Session()
sts = session.client(service_name='sts',
region_name=aws_settings['region'],
config=Config(retries={'max_attempts': 3})
)
assumed_role_object = sts.assume_role(
RoleArn="{0}".format(aws_settings['role_name']),
RoleSessionName='{0}'.format(aws_settings['role_session'])
)
# can be used ay name, but need to add restriction for the name!
ecr = session.client(aws_access_key_id=assumed_role_object['Credentials']['AccessKeyId'],
aws_secret_access_key=assumed_role_object['Credentials']['SecretAccessKey'],
aws_session_token=assumed_role_object['Credentials']['SessionToken'],
service_name=aws_settings['client'],
region_name=aws_settings['region'],
config=Config(retries={'max_attempts': 3})
)
return ecr
except Exception as err:
print("Failed to create a boto3 client connection to ecr:\n", str(err))
logger.error('ERROR: Failed to create a boto3 client connection to ecr')
return False
else:
print('Please use/set [--profile-name] or [--role-name] with [--role-session]')
return False
def get_ecr_repos(aws_settings):
ecr = ecr_connector(aws_settings)
if ecr:
try:
repos = ecr.describe_repositories()
print(repos)
print("The repos:\n {}!".format(repos))
except botocore.exceptions.ClientError as err:
error_code = str(err)
logger.error('ERROR: {0}. Forbidden Access!'.format(error_code))
else:
exit(-1)
return get_ecr_repos
def get_ecr_repo(aws_settings, ecr_repo):
ecr_repo_status = False
ecr = ecr_connector(aws_settings)
if ecr:
try:
repo = ecr.describe_repositories(repositoryNames=[ecr_repo])
# print("A repo {} is already exists!".format(ecr_repo))
ecr_repo_status = repo
return ecr_repo_status
except botocore.exceptions.ClientError as err:
error_code = str(err)
logger.error('ERROR: {0}. Forbidden Access!'.format(error_code))
ecr_repo_status = False
return ecr_repo_status
else:
exit(-1)
return ecr_repo_status
def get_authorization_token(aws_settings, ecr_repo):
global auth_token
ecr = ecr_connector(aws_settings)
ecr_repo = get_ecr_repo(aws_settings, ecr_repo)
ecr_repo_id = ecr_repo['repositories'][0]['registryId']
if ecr:
response = ecr.get_authorization_token(registryIds=[ecr_repo_id])
if response['ResponseMetadata']['HTTPStatusCode'] == 200:
auth_token = response['authorizationData'][0]['authorizationToken']
# print("Authorization token: ", auth_token)
elif response['ResponseMetadata']['HTTPStatusCode'] == 401:
print("You're not authorized")
exit(1)
else:
exit(-1)
return auth_token
def http_request(method='GET', url='', h=None, retries=False, timeout=30):
if h is None:
h = {}
http = urllib3.PoolManager()
response = http.request(method=method,
url=url,
headers=h,
retries=retries,
timeout=timeout)
if response.status == 200:
# print("response: ", response.data.decode('utf-8'))
logger.info('INFO: Successfully.....')
return response
elif response.status == 307:
# logger.error('HTTP 307 Temporary Redirect redirect status response')
return response
elif response.status == 401:
logger.error('ERROR: Please authorize, the issue: \n\t {}'.format(response.data.decode('utf-8')))
return response
elif response.status == 404:
logger.error('ERROR: 404 page not found')
return response
else:
logger.error('FAILURE: Got an error: \n\t {}'.format(response.data.decode('utf-8')))
return response
def urllib_request_urlopen(url):
response = urllib.request.urlopen(url).read()
return response
def downloading_layer(cache_dir=CACHE_DIR, layer_url=None, out_path='/', h=None):
"""
Get a layer in a compressed format, and saves it locally (unzipped).
The tar name is expected to contain a hash, thus to be cacheable.
"""
if h is None:
h = {}
cache_name = cache_dir + layer_url.split("/")[6].replace(':', '_')
repo_name = layer_url.split("/")[4]
response_headers = {}
if not os.path.exists(cache_name):
response = http_request(method='GET', url=layer_url, h=h, retries=False, timeout=30)
for key, val in response.headers.iteritems():
d = {key: val}
response_headers.update(d)
layer_location = response_headers['Location']
layer_location_data = urllib_request_urlopen(layer_location)
with open(cache_name, mode='wb') as localfile:
localfile.write(layer_location_data)
shutil.move(cache_name, cache_name)
os.makedirs(out_path[:out_path.rfind("/")], exist_ok=True)
shutil.copyfile(cache_name, out_path)
return downloading_layer
def ecr_pull(aws_settings, cname_url, ecr_repo, ecr_tag="latest", h=None):
if h is None:
h = {}
ecr = ecr_connector(aws_settings)
if ecr:
try:
manifests_url = cname_url + '/v2/{0}/manifests/{1}'.format(ecr_repo, ecr_tag)
response = http_request('GET', manifests_url, h)
web_manifest = json.loads(response.data.decode('utf-8'))
config_digest = web_manifest['config']['digest']
# ------------------------------------------------------------------------
config = cname_url + '/v2/{0}/blobs/{1}'.format(ecr_repo, config_digest)
response = http_request('GET', config, h)
response_headers = {}
for key, val in response.headers.iteritems():
d = {key: val}
response_headers.update(d)
config_location = response_headers['Location']
config_location_file = urllib_request_urlopen(config_location).decode('utf-8')
config_filename = config_digest.split(':')[1] + '.json'
with open(temp_dir + '/' + config_filename, 'w') as outfile:
json.dump(json.loads(config_location_file), outfile)
# ------------------------------------------------------------------------
layer_path_l = []
for layer in web_manifest['layers']:
layer_url = cname_url + '/v2/{0}/blobs/{1}'.format(ecr_repo, layer['digest'])
path = layer['digest'].split(':')[-1] + "/layer.tar"
out_path = temp_dir + '/' + path
downloading_layer(cache_dir=CACHE_DIR, layer_url=layer_url, out_path=out_path, h=h)
layer_path_l.append(path)
manifest = [{"Config": config_filename, "RepoTags": [], "Layers": layer_path_l}]
print("config_filename: ", config_filename)
print("manifest: ", manifest)
with open(temp_dir + '/' + 'manifest.json', 'w') as outfile:
json.dump(manifest, outfile)
with tarfile.open(ecr_tag, "w") as tar_out:
os.chdir(temp_dir)
tar_out.add(".")
except Exception as e:
logger.error('ERROR: {0}'.format(str(e)))
print(e)
exit(1)
else:
print("Could not get connect to AWS ECR or get needed repository")
exit(-1)
return ecr_pull
def ecr_push():
print("TBD")
return ecr_push
def ec2_handler(aws_settings, ecr_repo):
ecr = ec2_connector(aws_settings)
# TBD
return ec2_handler
if __name__ == '__main__':
start__time = time.time()
parser = argparse.ArgumentParser(prog='python3 script_name.py -h',
usage='python3 script_name.py {ARGS}',
add_help=True,
prefix_chars='--/',
epilog='''created by Vitalii Natarov'''
)
parser.add_argument('--version', action='version', version='v0.2.0')
parser.add_argument('--bclient', dest='boto3_client', help='Set boto3 client', default='ecr')
parser.add_argument('--region', dest='region', help='Set AWS region for boto3', default='us-east-1')
parser.add_argument('--pname', '--profile', dest='profile_name', help='Set profile name of AWS',
default=None)
parser.add_argument('--rname', '--role-name', dest='role_name', help='Set role ARN name',
default=None)
parser.add_argument('--rsession', '--role-session', dest='role_session', help='Set role session name',
default=None)
parser.add_argument('--registry-url', '--url', dest='registry_url', help='Set Registry URL',
default="https://docker-ecr.internal.logz.io")
parser.add_argument('--ecr-url', dest='ecr_url', help='Set URL from ECR registry',
default="406095609952.dkr.ecr.us-east-1.amazonaws.com")
parser.add_argument('--ecr-repo', '-repo', dest='ecr_repo', help='Set ECR repo name',
default="accounts")
parser.add_argument('--ecr-repo-tag', '-repo-tag', dest='ecr_repo_tag', help='Set ECR repo tag',
default="8f2b55cc45894247d880f7c4ac2042ed7c398dfa")
parser.add_argument('--ec2', dest='aws_ec2', help='Set ec2 usage', default='False')
results = parser.parse_args()
boto3_client = results.boto3_client
region = results.region
profile_name = results.profile_name
role_name = results.role_name
role_session = results.role_session
registry_url = results.registry_url
ecr_url_host = results.ecr_url
ecr_repo_name = results.ecr_repo
ecr_repo_tag = results.ecr_repo_tag
aws_ec2 = results.aws_ec2
try:
temp_dir = mkdtemp()
if aws_ec2 == 'True':
print("AWS EC2!")
aws_auth = {
"client": boto3_client,
"region": region,
"ec2_host": 'True'
}
ec2_handler(aws_auth)
else:
print("Local Usage!")
aws_auth = {
"client": boto3_client,
"region": region,
"profile_name": profile_name,
"role_name": role_name,
"role_session": role_session
}
authorization_token = get_authorization_token(aws_auth, ecr_repo_name)
headers = {
'Host': str(ecr_url_host),
'Accept': 'text/plain',
'X-Forwarded-Proto': 'https',
'X-Forwarded-For': '127.0.0.1',
'X-Real-IP': '66.66.66.66',
'Authorization': 'Basic {}'.format(str(authorization_token))
}
ecr_pull(aws_auth, registry_url, ecr_repo_name, ecr_repo_tag, headers)
finally:
shutil.rmtree(temp_dir)
end__time = round(time.time() - start__time, 2)
print("--- %s seconds ---" % end__time)
Использование — простое:
$ python3 ecr-containers.py --profile=default
config_filename: 2a5d611b6675bbcb15fea6050fdf5af2d974494511967e1ccd816efbe95fa348.json
manifest: [{'Config': '2a5d611b6675bbcb15fea6050fdf5af2d974494511967e1ccd816efbe95fa348.json', 'RepoTags': [], 'Layers': ['339de151aab4bc06eed8409daae147c408478cb538dacb90cc63f19ad4eba80b/layer.tar', 'c79c496f1543a6cf36a79305de7c709ea55c16b63ea86219c4b98c334b70488d/layer.tar', 'a5382bad4f98c8f742d943e2bd6930626b06af081c57062e06a501d449a4c472/layer.tar', '348e701aca2b0acab9fab3daaa10980e5507b8e55334671f503d1d5f5ef739a5/layer.tar', '965b2a30aa9c5ffea05d772b418c428cde9fa3f85faf37b2b66b719593f4c7b6/layer.tar', '9ee6edf857abe493670c386faa46127a9decea128da3fcafe25015afa8f6b9ef/layer.tar', '75f33f1b8076396b9a688c579ffb6ee4e7d7c83e94a9ba4d15b97a7efb118db7/layer.tar', 'a79e84406bd9b1f9c48e60589691a9ef807c7416cf1b2885eafc95fbbd3bbd8c/layer.tar', 'e5279c73940e27e2d0e32d8c288c32a795eeb12d4bf876e27067a7a49d032d6c/layer.tar', 'b088ed07f0856dbc5d7451536d3379a8c0dee79ddf98f7bdcef98e37549669fa/layer.tar', '09c3905aed6a2dd924c4a3fed0802d3cc191cdfc317c960ea9c43c9f8a4379c5/layer.tar', '7486d5d0bd29e293ed034751b9743c3f30405aa4746f353151ed44e2d827fc76/layer.tar']}]
--- 3.93 seconds ---
Скрипт поддерживает простой хелп, вызвать его можно так:
$ python3 ecr-containers.py -h
usage: python3 script_name.py {ARGS}
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--bclient BOTO3_CLIENT
Set boto3 client
--region REGION Set AWS region for boto3
--pname PROFILE_NAME, --profile PROFILE_NAME
Set profile name of AWS
--rname ROLE_NAME, --role-name ROLE_NAME
Set role ARN name
--rsession ROLE_SESSION, --role-session ROLE_SESSION
Set role session name
--registry-url REGISTRY_URL, --url REGISTRY_URL
Set Registry URL
--ecr-url ECR_URL Set URL from ECR registry
--ecr-repo ECR_REPO, -repo ECR_REPO
Set ECR repo name
--ecr-repo-tag ECR_REPO_TAG, -repo-tag ECR_REPO_TAG
Set ECR repo tag
--ec2 AWS_EC2 Set ec2 usage
created by Vitalii Natarov
После того как выполнили пуллинг образа, нужно его импортнуть в Докер:
$ docker load < 8f2b55cc45894247d880f7c4ac2042ed7c398dfa
32f366d666a5: Loading layer [==================================================>] 2.801MB/2.801MB
45449966e51a: Loading layer [==================================================>] 192.3MB/192.3MB
83ef90c94f12: Loading layer [==================================================>] 2.92MB/2.92MB
54037642f52c: Loading layer [==================================================>] 200kB/200kB
b9e5e90eb033: Loading layer [==================================================>] 42.09MB/42.09MB
539aca899eb8: Loading layer [==================================================>] 206B/206B
9d00a6a26f53: Loading layer [==================================================>] 4.668kB/4.668kB
bca0da0f1ea4: Loading layer [==================================================>] 1.631kB/1.631kB
cbb7b9b8cd31: Loading layer [==================================================>] 197.9MB/197.9MB
a0f1352db34e: Loading layer [==================================================>] 8.519kB/8.519kB
2543c13d39a0: Loading layer [==================================================>] 1.833kB/1.833kB
eb9876ca8f14: Loading layer [==================================================>] 41.2MB/41.2MB
Loaded image ID: sha256:ada32a4765be57eb1049808ebdbc7b8b6108847375383a21ffe004f3fffc3757
В плнах сделать push для работы с ECR, но это будет немного позже.
Репозиторий можно найти тут:
https://github.com/SebastianUA/ecr-pull-push
У меня все, статья «Pull/Push AWS ECR образов через AWS Route53 CNAME» завершена!
The post Pull/Push AWS ECR образов через AWS Route53 CNAME first appeared on linux-notes.org.]]>
Ключ GPG, используемый для подписания и проверки был изменен. Новые выпуски Terraform используют этот обновленный ключ для проверки официальных провайдеров, а официальные выпуски поставщика будут подписаны с помощью этого ключа.
Решений будет пару.
Для Terraporm 0.11.x вы можете установить версию AWS на V2.70.0:
provider "aws" {
region = "us-east-1"
version = "v2.70.0"
}
Или, просто при запуске Терраформа, использовать опцию:
$ terraform init -verify-plugins=false
Как-то так.
Решений будет пару.
Для Terraporm 0.11.x вы можете установить версию Azure на v1.44.0:
provider "azurerm" {
version = "v1.44.0"
}
Или, просто при запуске Терраформа, использовать опцию:
$ terraform init -verify-plugins=false
Как-то так.
У меня все, статья ‘openpgp: signature made by unknown entity в Terraform’ завершена.
The post openpgp: signature made by unknown entity в Terraform first appeared on linux-notes.org.]]>Есть пару способов как можно установить данную тулзовину себе на рабоче место.
Простой способ, выполнить:
$ export PROVIDER={all,google,aws,kubernetes}
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64
chmod +x terraformer-${PROVIDER}-linux-amd64
sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer
Так же, можно собрать пакет, склонировавши репу:
$ git clone https://github.com/GoogleCloudPlatform/terraformer.git
Идем далее.
Один из простых способов — это использовать HOMEBREW:
$ brew install terraformer
Еще можно выполнить:
$ export PROVIDER={all,google,aws,kubernetes}
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-darwin-amd64
chmod +x terraformer-${PROVIDER}-darwin-amd64
sudo mv terraformer-${PROVIDER}-darwin-amd64 /usr/local/bin/terraformer
Так же, можно собрать пакет, склонировавши репу:
$ git clone https://github.com/GoogleCloudPlatform/terraformer.git
Идем далее.
Запускаю первый пробный запуск и получаю ошибку:
$ terraformer import aws --resources=vpc,subnet --filter=vpc=default --regions=us-east-1
2021/05/31 17:59:22 aws importing region us-east-1
2021/05/31 17:59:22 open /Users/captain/.terraform.d/plugins/darwin_amd64: no such file or directory
Решением, — есть создание папок:
$ mkdir -p ~/.terraform.d/plugins/darwin_amd64
И пробую сново запустить, получаю:
$ terraformer import aws --resources=vpc,subnet --filter=vpc=default --regions=us-east-1
2021/05/31 18:01:14 aws importing region us-east-1
2021/05/31 18:01:14 fork/exec : no such file or directory
Решением есть, — скопировать бинарь от провайдера (в моем случае — это AWS), например:
$ cp -r Projects/Terraform/aws/examples/s3/.terraform/providers/registry.terraform.io/hashicorp/aws/3.42.0/darwin_amd64/terraform-provider-aws_v3.42.0_x5 ~/.terraform.d/plugins/darwin_amd64/
И запускаем еще раз:
$ terraformer import aws --resources=vpc,subnet --filter=vpc=default --regions=us-east-1
2021/05/31 18:13:30 aws importing region us-east-1
2021/05/31 18:13:33 aws importing... vpc
2021/05/31 18:13:34 aws done importing vpc
2021/05/31 18:13:34 aws importing... subnet
2021/05/31 18:13:35 aws done importing subnet
2021/05/31 18:13:35 Number of resources for service vpc: 0
2021/05/31 18:13:35 Number of resources for service subnet: 12
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-087ab3540e1a1ace4
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-049129ea82abc346a
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-06373f4c58dfe35a9
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-00db3165c99b03ee0
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-07021252bab163bcf
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-02b0ff71a1d00deb2
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-03212d250885f6986
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-04b6d772342323e4f
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-003e3e93d58873d28
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-081b69deddee10c61
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-01b817896302a1b98
2021/05/31 18:13:35 Refreshing state... aws_subnet.tfer--subnet-002D-029a45d1cf920abd6
2021/05/31 18:13:36 Filtered number of resources for service subnet: 12
2021/05/31 18:13:36 Filtered number of resources for service vpc: 0
2021/05/31 18:13:36 aws Connecting....
2021/05/31 18:13:36 aws save vpc
2021/05/31 18:13:36 aws save tfstate for vpc
2021/05/31 18:13:36 aws save subnet
2021/05/31 18:13:36 aws save tfstate for subnet
И так, я сгенерировал стек основываясь на VPC + subnets в определенном регионе. Сам statefile от Терраформа, можно найти по пути:
$ tree generated
generated
`-- aws
|-- subnet
| |-- outputs.tf
| |-- provider.tf
| |-- subnet.tf
| |-- terraform.tfstate
| `-- variables.tf
`-- vpc
|-- provider.tf
`-- terraform.tfstate
3 directories, 7 files
Так образом, можно получить всю структуру и при необходимости уменьшить трудозатраты на инвестигейт или рефакторинг существующей структуры
Помощь получить можно выполнив:
$ terraformer --help
Usage:
[command]
Available Commands:
help Help about any command
import Import current state to Terraform configuration
plan Plan to import current state to Terraform configuration
version Print the version number of Terraformer
Flags:
-h, --help help for this command
-v, --version version for this command
Use " [command] --help" for more information about a command.
Не всегда спасет. Но всегда может выручить!
Статья «Установка Terraformer в Unix/Linux» завершена.
The post Установка Terraformer в Unix/Linux first appeared on linux-notes.org.]]>Для начало что необходимо, так установить Кубернетес, у меня есть ряд статей на эту тему:
Установка Kubernetes кластера в Unix/Linux
Установка Kubernetes в Unix/Linux
Команды Kubernetes в Unix/Linux
Создание AWS EKS кластера в Unix/Linux
Установка minikube в Unix/Linux
После чего, создаем неймспейс:
$ kubectl create namespace argocd
Первое что необходимо, так — это поставить данную утилиту под названием kubectl!
Выполняем деплой:
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Можно выполнить установку еще так (Non-HA):
$ export VESION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
$ export ARGO_VERSION="v1.8.0-rc1"
$ kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo/${ARGO_VERSION}/manifests/install.yaml
Можно выполнить установку еще так (HA):
$ export ARGO_VERSION="v1.8.0-rc1"
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/${ARGO_VERSION}/manifests/ha/install.yaml
Первое что необходимо, так — это поставить данную утилиту под названием helm!
И выполняем deploy:
$ helm repo add argo https://argoproj.github.io/argo-helm
$ helm install argocd \
-n argocd \
--set global.image.repository="argoproj/argocd" \
--set global.image.tag="v1.8.1" \
--set server.service.type="LoadBalancer" \
argo/argo-cd
Если используете локальный миникуб или что-то такое, то запускаем так:
helm install argocd \
-n argocd \
--set global.image.repository="argoproj/argocd" \
--set global.image.tag="v1.8.1" \
argo/argo-cd
Проверим что все подымается так:
$ kubectl get po -n argocd && \
kubectl get service -n argocd
Можем идти дальше.
Кстати, пароль будет таким:
$ export OLD_ARGOCD_PWD=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2)
Если что, его можно поменять.
Я недавно писал модуль для работы с helm, и на примере ArgoCD выполнил деплой. Код выглядит так:
#
# MAINTAINER Vitaliy Natarov "[email protected]"
#
terraform {
required_version = "~> 0.13"
}
module "helm_release" {
source = "../../modules/release"
enable_release = true
release_name = "argocd-dev"
release_chart = "argo-cd"
release_repository = "https://argoproj.github.io/argo-helm"
release_version = "v1.7.6"
release_namespace = "argocd-dev"
release_create_namespace = true
release_values = []
release_set = [
{
name = "server.service.type"
value = "LoadBalancer"
}
]
release_set_sensitive = []
release_postrender = []
release_timeout = 600
release_force_update = false
release_recreate_pods = true
release_lint = false
}
Код с моими модулями можно найти тут — https://github.com/SebastianUA/terraform/blob/master/helm/examples/release/main.tf
Попозже дополню данную статью этим материалом.
Поле того, как у вас задеплоится ArgoCD, вы не можете знать пароль от стандартного пользователя (admin), но его можно посмотреть тут:
$ kubectl get secret -n argocd argocd-secret -o yaml
Или, так:
$ kubectl get secret -n argocd argocd-secret -o yaml | grep -Ei " admin.password: "
Т.к кубернетес пишет все секреты в base64, то декодировать строку можно так:
$ kubectl get secret -n argocd argocd-secret -o yaml | grep -Ei " admin.password: " | awk '{print $2}' | base64 --decode
Пока не понял как расшифровать пароль с BCrypt. По этому, пойду по простому пути, а именно — перепишу пароль на нужный, например, вы хотите поставить пароль «admin» — т.е как и логин. Дано:
$2b$10$ixLkbNDoNmoo3sHorEFequhJeEsZBtFVGlYjEhKZqBv2dlgTmbt.G
И выполняем патч:
$ kubectl -n argocd patch secret argocd-secret \
-p '{"stringData": {
"admin.password": "$2b$10$ixLkbNDoNmoo3sHorEFequhJeEsZBtFVGlYjEhKZqBv2dlgTmbt.G",
"admin.passwordMtime": "'$(date +%FT%T%Z)'"
}}'
Можно использовать login & password — admin.
Можно, просто выключить авторизацию так:
$ kubectl patch deploy argocd-server -n argocd -p '[{"op": "add", "path": "/spec/template/spec/containers/0/command/-", "value": "--disable-auth"}]' --type json
Посмотреть конфиг с юзерами и паролями, можно так:
$ kubectl get secret -n argocd argocd-secret -o yaml
Первое что нужно — это отредактировать:
$ kubectl edit -n argocd configmap/argocd-cm
И приводим к виду:
data:
accounts.vnatarov: apiKey, login
accounts.vnatarov.enabled: "true"
accounts.test: apiKey, login
accounts.test.enabled: "true"
Где:
Для пользователей я поставлю пароль по логину чтобы проверить как это будет работать.
Патчим пароли:
$ kubectl -n argocd patch secret argocd-secret \
-p '{"stringData": {
"vnatarov.password": "$2b$10$ySVNtxkJVrSmh2GQA2zTLOzNedw1QPtDMYXp0X21WYSFwqvVUdWfm",
"vnatarov.passwordMtime": "'$(date +%FT%T%Z)'"
}}'
kubectl -n argocd patch secret argocd-secret \
-p '{"stringData": {
"test.password": "$2b$10$O1Jc1FgWcDN.PC0mA6xdPOT4OmUQXHupcO9/0k6r6MHYLhuH7ALP6",
"test.passwordMtime": "'$(date +%FT%T%Z)'"
}}'
Или, можно отредактировать (но тогда нужно будет зашифровать фразу в base64):
$ kubectl edit secret -n argocd argocd-secret
Чет какие-то баги в аргоСД и я смог пофиксить способом что описал выше, по этому, выполнил вход в админку:
$ yes | argocd login 127.0.0.1:8080 --username admin --password admin
Можно поглядеть учетки:
$ argocd account list
NAME ENABLED CAPABILITIES
admin true login
test true login, apiKey
vnatarov true apiKey, login
Ну и обновляем пароль:
$ argocd account update-password --account test --new-password 'test'
Точно так же для моего другого юзера:
$ argocd account update-password --account vnatarov --new-password 'vnatarov'
*** Enter current password:
Password updated
Приведу полный вывод моего конфига configmap-ы argocd-cm:
$ kubectl get -n argocd configmap/argocd-cm -o yaml
apiVersion: v1
data:
accounts.test: login,apiKey
accounts.test.enabled: "true"
accounts.vnatarov: apiKey,login
accounts.vnatarov.enabled: "true"
application.instanceLabelKey: argocd.argoproj.io/instance
statusbadge.enabled: "true"
url: https://127.0.0.1:8080
users.anonymous.enabled: "true"
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
creationTimestamp: "2021-01-05T18:18:34Z"
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
helm.sh/chart: argo-cd-2.11.0
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:application.instanceLabelKey: {}
f:metadata:
f:annotations:
.: {}
f:meta.helm.sh/release-name: {}
f:meta.helm.sh/release-namespace: {}
f:labels:
.: {}
f:app.kubernetes.io/component: {}
f:app.kubernetes.io/instance: {}
f:app.kubernetes.io/managed-by: {}
f:app.kubernetes.io/name: {}
f:app.kubernetes.io/part-of: {}
f:helm.sh/chart: {}
manager: Go-http-client
operation: Update
time: "2021-01-05T18:18:34Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
f:accounts.test.enabled: {}
f:accounts.vnatarov.enabled: {}
f:statusbadge.enabled: {}
f:url: {}
f:users.anonymous.enabled: {}
manager: kubectl-edit
operation: Update
time: "2021-01-05T21:18:04Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
f:accounts.test: {}
f:accounts.vnatarov: {}
manager: argocd-server
operation: Update
time: "2021-01-05T21:32:26Z"
name: argocd-cm
namespace: argocd
resourceVersion: "122982"
selfLink: /api/v1/namespaces/argocd/configmaps/argocd-cm
uid: adc7f9e5-1318-44c7-a59e-ba1625a8f887
Приведу полный вывод моего конфига secret-а argocd-secret:
$ kubectl get secret -n argocd argocd-secret -o yaml
apiVersion: v1
data:
accounts.test.password: JDJhJDEwJEhyUW0uQlo2alFTRWxvT1J3N3BKMnVXOGVGLnVRUGc4cC5LQ2JSTGJqUzRtYWtWVDRZZ1dl
accounts.test.passwordMtime: MjAyMS0wMS0wNVQyMToyNzo0NFo=
accounts.test.tokens: bnVsbA==
accounts.vnatarov.password: JDJhJDEwJGExRElNNnk5SFhqM1h3ZmZjMkFNa094eGdROUYzTTg0OUQ2M1BoOFhnZXB3VkNrc2ZoZnYy
accounts.vnatarov.passwordMtime: MjAyMS0wMS0wNVQyMTozMjoyNlo=
accounts.vnatarov.tokens: bnVsbA==
admin.password: JDJiJDEwJGl4TGtiTkRvTm1vbzNzSG9yRUZlcXVoSmVFc1pCdEZWR2xZakVoS1pxQnYyZGxnVG1idC5H
admin.passwordMtime: MjAyMS0wMS0wNVQyMDoyMTowNFo=
server.secretkey: MDZ5QVA3WVZ4cTQ0ZDFDdXZzaEZqZjcydDZmUmVmdjQ0UXFsenhUWDZEcz0=
test.password: JDJiJDEwJE8xSmMxRmdXY0ROLlBDMG1BNnhkUE9UNE9tVVFYSHVwY085LzBrNnI2TUhZTGh1SDdBTFA2
test.passwordMtime: MjAyMS0wMS0wNVQyMjo0NTozNEVFVA==
tls.crt: YYYYY=
tls.key: XXXXXXX==
vnatarov.password: JDJiJDEwJHlTVk50eGtKVnJTbWgyR1FBMnpUTE96TmVkdzFRUHRETVlYcDBYMjFXWVNGd3F2VlVkV2Zt
vnatarov.passwordMtime: MjAyMS0wMS0wNVQyMjoyNjo0N0VFVA==
kind: Secret
metadata:
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
creationTimestamp: "2021-01-05T18:18:34Z"
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-secret
app.kubernetes.io/part-of: argocd
helm.sh/chart: argo-cd-2.11.0
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:meta.helm.sh/release-name: {}
f:meta.helm.sh/release-namespace: {}
f:labels:
.: {}
f:app.kubernetes.io/component: {}
f:app.kubernetes.io/instance: {}
f:app.kubernetes.io/managed-by: {}
f:app.kubernetes.io/name: {}
f:app.kubernetes.io/part-of: {}
f:helm.sh/chart: {}
f:type: {}
manager: Go-http-client
operation: Update
time: "2021-01-05T18:18:34Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
f:admin.password: {}
f:test.password: {}
f:test.passwordMtime: {}
f:vnatarov.password: {}
f:vnatarov.passwordMtime: {}
manager: kubectl-patch
operation: Update
time: "2021-01-05T20:45:35Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:accounts.test.password: {}
f:accounts.test.passwordMtime: {}
f:accounts.test.tokens: {}
f:accounts.vnatarov.password: {}
f:accounts.vnatarov.passwordMtime: {}
f:accounts.vnatarov.tokens: {}
f:admin.passwordMtime: {}
f:server.secretkey: {}
f:tls.crt: {}
f:tls.key: {}
manager: argocd-server
operation: Update
time: "2021-01-05T21:32:26Z"
name: argocd-secret
namespace: argocd
resourceVersion: "122983"
selfLink: /api/v1/namespaces/argocd/secrets/argocd-secret
uid: 17e9ff5c-946d-4655-bd05-c983091ef210
type: Opaque
Приведу полный вывод моего конфига secret-а argocd-secret:
$ kubectl get -n argocd configmap/argocd-rbac-cm -o yaml
apiVersion: v1
data:
policy.csv: |
# Built-in policy which defines two roles: role:readonly and role:admin,
# and additionally assigns the admin user to the role:admin role.
# There are two policy formats:
# 1. Applications (which belong to a project):
# p, <user/group>, <resource>, <action>, <project>/<object>
# 2. All other resources:
# p, <user/group>, <resource>, <action>, <object>
p, role:readonly, applications, get, */*, allow
p, role:readonly, certificates, get, *, allow
p, role:readonly, clusters, get, *, allow
p, role:readonly, repositories, get, *, allow
p, role:readonly, projects, get, *, allow
p, role:readonly, accounts, get, *, allow
p, role:readonly, gpgkeys, get, *, allow
p, role:admin, applications, create, */*, allow
p, role:admin, applications, update, */*, allow
p, role:admin, applications, delete, */*, allow
p, role:admin, applications, sync, */*, allow
p, role:admin, applications, override, */*, allow
p, role:admin, applications, action/*, */*, allow
p, role:admin, certificates, create, *, allow
p, role:admin, certificates, update, *, allow
p, role:admin, certificates, delete, *, allow
p, role:admin, clusters, create, *, allow
p, role:admin, clusters, update, *, allow
p, role:admin, clusters, delete, *, allow
p, role:admin, repositories, create, *, allow
p, role:admin, repositories, update, *, allow
p, role:admin, repositories, delete, *, allow
p, role:admin, projects, create, *, allow
p, role:admin, projects, update, *, allow
p, role:admin, projects, delete, *, allow
p, role:admin, accounts, update, *, allow
p, role:admin, gpgkeys, create, *, allow
p, role:admin, gpgkeys, delete, *, allow
g, role:admin, role:readonly
g, admin, role:admin
g, vnatarov, role:admin
policy.default: role:readonly
kind: ConfigMap
metadata:
annotations:
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
creationTimestamp: "2021-01-05T18:18:34Z"
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-rbac-cm
app.kubernetes.io/part-of: argocd
helm.sh/chart: argo-cd-2.11.0
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.: {}
f:meta.helm.sh/release-name: {}
f:meta.helm.sh/release-namespace: {}
f:labels:
.: {}
f:app.kubernetes.io/component: {}
f:app.kubernetes.io/instance: {}
f:app.kubernetes.io/managed-by: {}
f:app.kubernetes.io/name: {}
f:app.kubernetes.io/part-of: {}
f:helm.sh/chart: {}
manager: Go-http-client
operation: Update
time: "2021-01-05T18:18:34Z"
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:policy.csv: {}
f:policy.default: {}
manager: kubectl-edit
operation: Update
time: "2021-01-05T20:34:00Z"
name: argocd-rbac-cm
namespace: argocd
resourceVersion: "116734"
selfLink: /api/v1/namespaces/argocd/configmaps/argocd-rbac-cm
uid: aa1649df-d477-4258-bb3a-f7219326ad84
Можно юзать!
Патчим:
$ kubectl patch deploy argocd-server -n argocd -p '[{"op": "add", "path": "/spec/template/spec/containers/0/command/-", "value": "--insecure"}]' --type json
И потом все норм.
Команда простая (на примере дефолтного админа):
$ kubectl -n argocd create rolebinding default-admin --clusterrole=admin --serviceaccount=argo:default
Дальше — больше.
Создаем это так:
$ cat <<EoF > argo-patch.yaml
data:
config: |
artifactRepository:
s3:
endpoint: s3.amazonaws.com
bucket: batch-artifact-repository
EoF
Где:
И применяем:
$ kubectl -n argocd patch \
configmap/argocd-cm \
--patch "$(cat argo-patch.yaml)"
Вот так вот.
Установка очень простая:
$ kubectl apply -f https://operatorhub.io/install/argocd-operator-helm.yaml
После чего, проверяем:
$ kubectl get csv -n my-argocd-operator-helm
Или, еще проще способ:
$ curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.17.0/install.sh | bash -s v0.17.0
После чего, проверяем:
$ kubectl get csv -n olm
Вот и все.
Пропишу команду для дальнейшего использования:
$ export ARGOCD_SERVER=$(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2)
Т.к я выбрал локальный запуск и приложение не смотрит в мир, то нужно выполнить форвардинг порта:
$ kubectl port-forward service/argocd-server -n argocd 8080:443
И после данного действия, у вас будет работать argoCD на 127.0.0.1:8080
Т.к я использую макбук, то следующая команда установит argocd CLI на мой мак:
$ brew install argocd
Далее, выполним логин:
$ argocd login localhost:8080 --insecure --username admin --grpc-web
NOTE: Нужно знать пароль!
Далее, ставим 1-е приложение:
$ argocd app create guestbook \
--repo https://github.com/pcrete/argocd-example-apps.git \
--path guestbook \
--dest-server https://kubernetes.default.svc \
--dest-namespace guestbook
И далее, ставим 2-е приложение:
$ argocd app create webapp \
--repo https://gitlab.com/gitops-argocd-demo/webapp-chart.git \
--path . \
--dest-server https://kubernetes.default.svc \
--dest-namespace hello-gitops \
--sync-policy automated \
--auto-prune \
--self-heal
Можно открыть в браузере аргоСД и поглядеть что оно будет делать.
Вот и все, статья «Установка ArgoCD в Unix/Linux» завершена.
The post Установка ArgoCD в Unix/Linux first appeared on linux-notes.org.]]>Установка очень простая и приведу пару примеров как можно установить желаемую тулзу.
Для начала, стоит установить HOMEBREW, и после чего, выполняем установку:
$ brew install warrensbox/tap/tfswitch
Перейдем к настройке и использовании.
Для Линукса, разработчики предусмотрели шел-скрипт:
$ curl -L https://raw.githubusercontent.com/warrensbox/terraform-switcher/release/install.sh | bash
Или, через Snapcraft для CentOS, Ubuntu, Linux Mint, RHEL, Debian, Fedora:
$ sudo snap install tfswitch
Или, можно скомпилить тулу с исходного кода:
$ git clone https://github.com/warrensbox/terraform-switcher.git
Можно использовать!
Если вы используете bash, то для автоматического переключения можно добавить следующую настройку в «~/.bashrc»:
cdtfswitch(){
builtin cd "$@";
cdir=$PWD;
if [ -e "$cdir/.tfswitchrc" ]; then
tfswitch
fi
}
alias cd='cdtfswitch'
Замечание, — можно использовать «.tfswitchrc» или «.tfswitch.toml» или «.terraform-version».
Если вы используете zsh, то для автоматического переключения можно добавить следующую настройку в «~/.zshrc»:
load-tfswitch() {
local tfswitchrc_path=".tfswitchrc"
if [ -f "$tfswitchrc_path" ]; then
tfswitch
fi
}
add-zsh-hook chpwd load-tfswitch
load-tfswitch
Если вы используете fish, то для автоматического переключения можно добавить следующую настройку в «~/.config/fish/config.fish»:
function switch_terraform --on-event fish_postexec
string match --regex '^cd\s' "$argv" > /dev/null
set --local is_command_cd $status
if test $is_command_cd -eq 0
if count *.tf > /dev/null
grep -c "required_version" *.tf > /dev/null
set --local tf_contains_version $status
if test $tf_contains_version -eq 0
command tfswitch
end
end
end
end
Как-то так.
Переходим в проект с Терраформ кодом и выполняем:
~/Projects/Terraform/aws/examples/transit_gateway dev tfswitch
Reading required version from terraform file, constraint: ~> 0.13
Matched version: 0.13.5
2020/12/08 19:51:46 Creating directory for terraform: /Users/captain/.terraform.versions/
Downloading https://releases.hashicorp.com/terraform/0.13.5/terraform_0.13.5_darwin_amd64.zip to terraform_0.13.5_darwin_amd64.zip
Downloading ...
35665893 bytes downloaded.
Switched terraform to version "0.13.5"
~/Projects/Terraform/aws/examples/transit_gateway dev
После этого, tfswitch скачает нужную версию ПО которая описана в вашем файле:
terraform {
required_version = "~> 0.13"
}
Например, можно внедрить tfswitch в Jenkins пайплайну:
#!/bin/bash
echo "Installing tfswitch locally"
wget https://raw.githubusercontent.com/warrensbox/terraform-switcher/release/install.sh #Get the installer on to your machine
chmod 755 install.sh #Make installer executable
./install.sh -b `pwd`/.bin #Install tfswitch in a location you have permission
CUSTOMBIN=`pwd`/.bin #set custom bin path
export PATH=$PATH:$CUSTOMBIN #Add custom bin path to PATH environment
$CUSTOMBIN/tfswitch -b $CUSTOMBIN/terraform 0.11.7 #or simply tfswitch -b $CUSTOMBIN/terraform 0.11.7
terraform -v #testing version
Так же, можно внедрить tfswitch в Circle CI пайплайну:
version: 2
jobs:
build:
docker:
- image: ubuntu
working_directory: /go/src/github.com/warrensbox/terraform-switcher
steps:
- checkout
- run:
command: |
set +e
apt-get update
apt-get install -y wget
rm -rf /var/lib/apt/lists/*
echo "Installing tfswitch locally"
wget https://raw.githubusercontent.com/warrensbox/terraform-switcher/release/install.sh #Get the installer on to your machine
chmod 755 install.sh #Make installer executable
./install.sh -b `pwd`/.bin #Install tfswitch in a location you have permission
CUSTOMBIN=`pwd`/.bin #set custom bin path
export PATH=$PATH:$CUSTOMBIN #Add custom bin path to PATH environment
$CUSTOMBIN/tfswitch -b $CUSTOMBIN/terraform 0.11.7 #or simply tfswitch -b $CUSTOMBIN/terraform 0.11.7
terraform -v #testing version
Вот и все, статья «Установка tfswitch в Unix/Linux» завершена.
The post Установка tfswitch в Unix/Linux first appeared on linux-notes.org.]]>Можно попробовать любой динамический процесс прямо с терминала — наблюдать за изменениями в базе данных, отслеживать сообщения MQ в полете, запускать сценарий развертывания и получать уведомление, когда это будет сделано.
Если есть способ получить метрику с помощью командной строки, то ее можно мгновенно визуализировать с помощью Sampler.
Для начала, нужно поставить HOMEBREW:
А потом выполняем установку:
$ brew install sampler
Или:
$ sudo curl -Lo /usr/local/bin/sampler https://github.com/sqshq/sampler/releases/download/v1.1.0/sampler-1.1.0-darwin-amd64 && sudo chmod +x /usr/local/bin/sampler
Использование будет ниже.
Установка выглядит:
$ sudo wget https://github.com/sqshq/sampler/releases/download/v1.1.0/sampler-1.1.0-linux-amd64 -O /usr/local/bin/sampler && sudo chmod +x /usr/local/bin/sampler
Для проигрывания звука, нужно поставить libasound2-dev пакет, например для Debian/Ubuntu:
$ sudo apt install libasound2-dev
Для Fedora:
$ sudo dnf install golang-github-sqshq-sampler
Перейдем к использованию.
Вы указываете команды CLI-шки, Sampler выполнит и выведет на экран.
Использование Sampler — это, по сути, трехэтапный процесс:
Конфиг выглядит:
theme: dark # default = dark ; light supports also.
variables:
sshconnection: ssh USER@HOST
mysql_connection: mysql -u root -s --database mysql --skip-column-names
textboxes:
- title: Docker containers stats
sample: docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"
- title: SSH
pty: true
init: $sshconnection
sample: top
- title: Java application uptime
multistep-init:
- java -javaagent:/Users/captain/jmx_prometheus_javaagent-0.14.1.jar=8080
- open localhost:8080 # or local PID
- bean java.lang:type=Runtime
sample: get Uptime
transform: echo $sample | tr -dc '0-9' | awk '{printf "%.1f min", $1/1000/60}'
sparklines:
- title: CPU usage
sample: ps -A -o %cpu | awk '{s+=$1} END {print s}'
- title: MySQL (random number example)
pty: true
init: $mysql_connection
sample: select rand();
Простой запуск:
$ sampler -c sampler.yaml
Идея прикольная! Использовать можно, но пока практичности не нашел. Оставил чтобы можно было ознакомиться в случае чего.
Вот и все, статья «Установка sampler в Unix/Linux» завершена.
The post Установка sampler в Unix/Linux first appeared on linux-notes.org.]]>Модуль Погода Сенсор Температура и влажности Давление освещения Сенсор CJMCU
Хватит описаний, приступаем…..
Первое что необходимо сделать — установить и настроить вашу малинку. Я описывал процесс установки в своей статье:
Установка Raspbian from scratch на Unix/Linux
Я заказывал на алиэкспресс по запросу «HTU21D + BMP180 + BH1750FVI Модуль Погода Сенсор Температура и влажности Давление освещения Сенсор CJMCU». Не знаю почему, но выбрал именно эту микросхему. В ней имееться несколько датчиков с которыми можно будет разобраться как это все работает. При необходимости, я всегда могу купить другой вариант.
Данная микросхема выглядит вот так:

Имееться 4 пина:
Погуглил распиновку и решил добавить ее сюда для дальнейшего юседжа:

Собственно, подключаем микруху по описанию пинов. Там всего их 4 шт, по этому — думаю что не составит труда все вставить как нужно.
Сейчас, стоит включить некоторые интерфейсы для работы с датчиками, для этого, выполняем следующую команду:
# raspi-config
Выглядит это вот так:

Нас интересует «Interfacing Options». Переходим на данный пункт и кликаем «enter». Следующим действием включаем «SPI»:

Выбираем что необходимо включить/выключить и жмакаем «enter». Затем, выбираем что нужно, включить «YES» или выключить «NO».
Аналогичными действиями, включаем «1-Wire» и «I2C».
Замечание: Если у вас /boot раздел смонтирован в read-only (ro), то стоит отредактировать /etc/fstab и убрать данную опцию или добавить write (rw) и после чего, выполнить reboot.
Ну, для начала, обновим ОС:
# apt update && apt dist-upgrade
Ставим пакет для python3:
# pip3 install sensor i2csense
Если нужно уставить PIP, то вот статья:
Установка pip/setuptools/wheel в Unix/Linux
Ставим пакеты:
# apt install -y i2c-tools python3-smbus
Для работы с htu21d и python3 стоит поставить пакет:
# pip3 install adafruit-circuitpython-htu21d lm-sensors
Для работы с другими модулями/датчиками и python3 стоит поставить пакет:
# apt install -y python3-pigpio rpi.gpio python3-gpiozero
Иницилиазируем pigpiod либу:
# pigpiod
Если получили ошибку:
2019-05-29 02:17:32 initInitialise: Can't lock /var/run/pigpio.pid
Can't initialise pigpio library
Решение:
# rm -f /var/run/pigpio.pid && killall pigpiod && pigpiod
Можно идти дальше.
Проверим, работает ли модуль i2c, с помощью следующей команды:
# lsmod | grep i2c_
i2c_bcm2835 16384 0
i2c_dev 16384 0
Смотрим датчики которые используют 1-wire:
# ls /sys/bus/w1/devices/
00-03b000000000 00-7db000000000 00-fdb000000000 w1_bus_master1
Смотрим датчики которые используют SPI:
# i2cdetect -y 0
Error: Could not open file `/dev/i2c-0' or `/dev/i2c/0': No such file or directory
Смотрим датчики которые используют I2C:
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
Или вот еще утилита которая может определить сенсоры:
# i2csense
Running i2cdetect utility in i2c bus 1:
The command '/usr/sbin/i2cdetect -y 1' has returned:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
3 sensors detected in 0x23, 0x40, 0x77
Еще полезности:
# cat /sys/bus/i2c/devices/i2c-*/name
bcm2835 I2C adapter
Или:
# i2cdetect -l
i2c-1 i2c bcm2835 I2C adapter I2C adapter
Идем дальше.
Пример 1, открываем файл:
$ vim htu21d_sensor/htu21d_sensor.py
И прописываем:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Adafruit_HTU21D.HTU21D import HTU21D
sensor = HTU21D()
temperature = sensor.read_temperature()
humidity = sensor.read_humidity()
dewpoint = sensor.read_dewpoint()
print("Temperature(Температура): {}C".format(round(temperature, 1)))
print("Humidity(Влажность): {}%".format(round(humidity, 1)))
print("Dewpoint: {}".format(round(dewpoint, 1)))
sensor.reset()
Запускаем:
$ python3 htu21d_sensor/htu21d_sensor.py
Temperature(Температура): 36.5C
Humidity(Влажность): 22.9%
Dewpoint: 12.1
Честно, температура явно не такая. Попробую разобраться попозже. А для тестов — пойдет и так (хотя и печальненько….).
Вот и все, статья «Умный дом с HTU21D + BMP180 + BH1750FVI и Raspberry pi 3+» завершина.
The post Умный дом с HTU21D + BMP180 + BH1750FVI и Raspberry pi 3+ first appeared on linux-notes.org.]]>Для начала, смотрим какие аппликейшены запущены в EMR:
$ yarn application -list
Из полученного списка, берем ИД джобы и прибиваем ее:
$ yarn application -kill <jobid>
Убиваем все джобы:
$ yarn_app_list=$(yarn application -list 2>1 | awk '{if ($7 =="UNDEFINED" && $6 == "ACCEPTED") print $1; }') && \
yarn application -kill $(echo "$yarn_app_list"| xargs -I{} -n1 echo {})
Вот и все, статья «Очистка джоб в EMR/Hadoop в Unix/Linux» завершена.
The post Очистка джоб в EMR/Hadoop в Unix/Linux first appeared on linux-notes.org.]]>awless — представляет собой мощный, инновационный и небольшой интерфейс командной строки (CLI) для управления веб-службами Amazon.
Awless имеет следующие характеристики:
Приступим к установке.
Установка очень простая.
Для начала, ставим HOMEBREW:
И после чего, выполняем:
$ brew tap wallix/awless; brew install awless
После чего, можно добавить автодополнения в zsh:
source /usr/local/share/zsh/site-functions/_awless
Можно использовать программу. Примеры предоставлю ниже.
Установка на Linux, очень простая, стоит только запустить:
$ curl https://raw.githubusercontent.com/wallix/awless/master/getawless.sh | bash
Добавляем в zsh автодополнение команд:
$ echo 'source <(awless completion zsh)' >> ~/.zshrc
Для bash, аналогично:
$ echo 'source <(awless completion bash)' >> ~/.bashrc
Для помощи использования дополнения, выполните:
$ awless completion --help
Или, если имеется Golang в системе, выполняем:
$ go get -u github.com/wallix/awless
Можно использовать программу. Примеры предоставлю ниже.
Наверное, самое первое что нужно отметить, — получение помощи:
$ awless --help
Или, для команды, можно использовать такой синтаксис:
$ awless list --help
Пример использования утилиты, для вывода ресурсов, например:
$ awless list instances --sort uptime
$ awless list users --format csv
$ awless list volumes --filter state=use --filter type=gp2
$ awless list volumes --tag-value Purchased
$ awless list vpcs --tag-key Dept --tag-key Internal
$ awless list instances --tag Env=Production,Dept=Marketing
$ awless list instances --filter state=running,type=micro
$ awless list s3objects --filter bucket=pdf-bucket
Можно посмотреть конфиг который используете:
$ awless config
Выставляем новую переменную для утилиты, например:
$ awless config set aws.profile
Value ? > default
Это выставит дефалтный профиль (он и так по умолчанию такой, но можно выставить любой другой).
Можно выставить любую переменную, например:
$ awless config set aws.var_here
Value ? > i_m_variable
Если проверить, получим:
$ awless config | grep aws.var_here
[info] region precedence: 'us-east-1' loaded through profile 'default' (see AWS config files $HOME/.aws/{credentials,config})
aws.var_here: i_m_variable (string)
Убрать ее можно так:
$ awless config unset aws.var_here
Можно проанализировать (размер AWS S3 бакета, цену EBS, или отсканировать порты):
$ awless inspect -i bucket_sizer
$ awless inspect -i pricer
$ awless inspect -i port_scanner
Смотрим логи:
$ awless log --full
$ awless log --raw
$ awless log --short
Можно выгребсти различную инфу через «show» опцию:
$ awless show {your_user,instance_id}
Подключиться к сервисам можно одним из способов:
$ awless ssh i-8d43b21b
$ awless ssh redis-prod
$ awless ssh ec2-user@redis-prod
$ awless ssh 34.215.29.221
$ awless ssh [email protected] --port 23
$ awless ssh redis-prod -i keyname
$ awless ssh redis-prod -i ~/path/toward/key
$ awless ssh db-private --through my-bastion
$ awless ssh db-private --private
$ awless ssh redis-prod --print-cli
$ awless ssh redis-prod --print-config
$ awless ssh private-redis --through my-proxy
$ awless ssh private-redis --through my-proxy --through-port 23
$ awless ssh 172.31.77.151 --port 2222 --through my-proxy --through-port 23
Можно переключаться между настройками, например:
$ awless switch eu-west-2
$ awless switch mfa
$ awless switch default us-west-1
$ awless sw eu-west-3 admin
Можем засинкать некоторые ресурсы:
$ awless sync
И так далее, я не буду приводить много примеров т.к тула очень простая и удобна в работе.
Вот и все, статья «Установка awless в Unix/Linux» завершена.
The post Установка awless в Unix/Linux first appeared on linux-notes.org.]]>Структура моего .github фолдера выглядит так:
$ tree .github | grep -Ev "_BK"
.github
|-- FUNDING.yml
|-- ISSUE_TEMPLATE
| |-- bug_report.md
| |-- custom.md
| `-- feature_request.md
|-- actions
|-- lock.yml
|-- move.yml
|-- no-response.yml
|-- stale.yml
`-- workflows
|-- terraform-lint.yaml
3 directories, 11 files
Где:
GitHub Actions позволяют создавать собственные рабочие процессы жизненного цикла разработки программного обеспечения (SDLC) непосредственно в вашем репозитории GitHub.
Мой самый простой lint для Terraform выглядит:
$ cat .github/workflows/terraform-lint.yaml
---
name: terraform-lint
on: [push, pull_request]
jobs:
delivery:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@master
- name: Lint Terraform
uses: actionshub/terraform-lint@master
Я не создавал экшены и взял готовое использование проекта ( написанного кем-то до меня).
Еще, имеется и другой пример использование:
---
name: 'Terraform GitHub Actions'
# on:
# pull_request:
# branches:
# - master
on:
- pull_request
jobs:
terraform:
name: 'Terraform'
runs-on: ubuntu-latest
steps:
- name: 'Check out code'
uses: actions/checkout@master
- name: 'Terraform Format'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: 0.12.13
tf_actions_subcommand: 'fmt'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 'Terraform Init'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: 0.12.13
tf_actions_subcommand: 'init'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TF_ACTION_WORKING_DIR: '.'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: 'Terraform Validate'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: 0.12.13
tf_actions_subcommand: 'validate'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 'Terraform Plan'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: 0.12.13
tf_actions_subcommand: 'plan'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ЗАМЕЧАНИЕ: В данном примере — использую secrets, которые нужно прописать в настройках самого проекта. Данную настройку можно найти по следующему пути:
<GITHUB_URL>/<YOUR_USER>/<YOUR_REPO_NAME>/settings/secrets
Где:
Например у меня это выглядит так:
https://github.com/SebastianUA/terraform/settings/secrets
Нашел в интернете «runatlantis» проект который позволяет выполнять действия (terraform plan, terraform apply — это как пример) написав команду в комментарии ( например pull request-а). Не проверял работу, но оставил чтобы не забыть про него, если нужно будет заюзать.
Вот и все, статья «Создаем GitHub workflows с actions в Unix/Linux» завершена.
The post Создаем GitHub workflows с actions в Unix/Linux first appeared on linux-notes.org.]]>