-
kubectl plugin - SOCKS5 proxy to Services or Pods in the cluster
I’ve published a new kubectl plugin called kubectl-plugin-socks5-proxy. This is a kubectl plugin that creates a local SOCKS5 proxy through which you can access to Services or Pods in a Kubernetes cluster.
What the plugin actually does is that it create a SOCKS proxy server Pod in a Kubernetes cluster and forwards a local port (default:1080) to the proxy. So you can access to Servcies or Pods in Kuberenetes cluster by using the local port as SOCKS5 proxy like this:
curl --socks5-hostname localhost:1080 http://httpbin.default.svc.cluster.local/headers
Installation
This is a way to install the plugin through krew. After installing krew by following this, you can install the plugin like this:
kubectl krew install socks5-proxy
You can search the plugin with a keyword like this:
kubectl krew search socks5 NAME DESCRIPTION INSTALLED socks5-proxy SOCKS5 proxy to Services or Pods in the cluster no
After installed the plugin, you can run the plugin like this:
kubectl socks5-proxy
How to use
Usage
Usage: kubectl socks5-proxy Options: -n, --namespace <namespace> Namespace to create SOCKS5 proxy server in -p, --port <local port> Local port to be forwarded to the SOCKS5 proxy server (Pod). A client connects to this port, then the connection is forwarded to the SOCKS5 proxy server, which is then forwareded to the destination server --skip-cleanup-proxy Skip cearning up SOCKS5 proxy pod Default: Cleaning up SOCKS5 proxy pod at the end -h, --help Show this message
Deploy an sample app and Create SOCKS5 proxy
Suppose you deploy a sample app in a Kubernetes cluster like this
git clone https://github.com/yokawasa/kubectl-plugin-socks5-proxy.git cd kubectl-plugin-socks5-proxy kubectl apply -f sample-apps/party-clippy.yaml kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 96d party-clippy ClusterIP 10.0.5.226 <none> 80/TCP 1m
First of all, create a local SOCKS5 proxy (default: 1080 port) by running
kubectl socks5-proxy
like this:kubectl socks5-proxy using: namespace=default using: port=1080 Creating Socks5 Proxy (Pod)... pod/socks5 created Forwarding from 127.0.0.1:1080 -> 1080 Forwarding from [::1]:1080 -> 1080
Use SOCKS5 Proxy in Curl
Now you can access Srvices or Pods in the Kubernetes cluster from a local machine by using the local port as SOCKS proxy in Curl
# Service name curl --socks5-hostname localhost:1080 party-clippy # Service name curl --socks5-hostname localhost:1080 http://party-clippy # FQDN curl --socks5-hostname localhost:1080 http://party-clippy.default.svc.cluster.local
_________________________________ / It looks like you're building a \ \ microservice. / --------------------------------- \ \ __ / \ | | @ @ | | || | / || || |\_/| \___/
Use SOCKS5 Proxy in Google Chrome browser
First, let’s configuring your Chrome browser to use SOCKS5 proxy like this:
Linux
/usr/bin/google-chrome \ --user-data-dir="$HOME/proxy-profile" \ --proxy-server="socks5://localhost:1080"
macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ --user-data-dir="$HOME/proxy-profile" \ --proxy-server="socks5://localhost:1080"
Windows
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" ^ --user-data-dir="%USERPROFILE%\proxy-profile" ^ --proxy-server="socks5://localhost:1080"
See also How to Set up SSH SOCKS Tunnel for Private Browsing
NOTE: The –proxy-server=”socks5://yourproxy:1080” flag tells Chrome to send all http:// and https:// URL requests through the SOCKS proxy server “yourproxy:1080”, using version 5 of the SOCKS protocol. The hostname for these URLs will be resolved by the proxy server, and not locally by Chrome. ref: Configuring a SOCKS proxy server in Chrome
Now you are ready to access Services or Pods in the Kubernetes cluster with your Chrome browser
Enjoy the plugin!!
-
GitHub Actions - Kubernetes tools installer
I’ve published a new GitHub Action called action-setup-kube-tools (View on Marketplace). The action installs Kubernetes tools (kubectl, kustomize, helm, kubeval, conftest, and yq) and cache them on the runner. This is a typescript version of stefanprodan/kube-tools with no command input param.
Usage
Inputs
Parameter Required Default Value Description kubectl
false
1.18.2
kubectl version. kubectl vesion can be found here kustomize
false
3.5.5
kustomize version. kustomize vesion can be found here helm
false
2.16.7
helm version. helm vesion can be found here helmv3
false
3.2.1
helm v3 version. helm v3 vesion can be found here kubeval
false
0.15.0
kubeval version. kubeval vesion can be found here conftest
false
0.19.0
conftest version. conftest vesion can be found here rancher
false
2.4.10
Rancher CLI version. Rancher CLI vesion can be found here Supported Environments: Linux
Outputs
Parameter Description kubectl_path
kubectl command path kustomize_path
kustomize command path helm_path
helm command path helmv3_path
helm v3 command path kubeval_path
kubeval command path conftest_path
conftest command path yq_path
yq command path rancher_path
rancher command path Sample Workflow
Specific versions for the commands can be setup by adding inputs parameters like this:
test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - uses: yokawasa/action-setup-kube-tools@v0.1.0 with: kubectl: '1.17.1' kustomize: '3.7.0' helm: '2.16.7' helmv3: '3.2.4' kubeval: '0.14.0' conftest: '0.18.2' rancher: '2.4.10' id: setup - run: | kubectl version --client kustomize version helm version --client helmv3 version kubeval --version conftest --version yq --version rancher --version
Default versions for the commands will be setup if you don’t give any inputs like this:
test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - uses: yokawasa/action-setup-kube-tools@v0.1.0 id: setup - run: | kubectl version --client kustomize version helm version --client helmv3 version kubeval --version conftest --version yq --version rancher --version
Developing the action
Install the dependencies
npm install
Build the typescript and package it for distribution by running ncc
npm run build && npm run pack
Finally push the resutls
git add dist git commit -a -m "prod dependencies" git push origin releases/v0.1.0
Enjoy the action!
-
GitHub Actions - Elastic Cloud Control (ecctl) tool installer
I’ve published a new GitHub Action called action-setup-ecctl (View on Marketplace). The action installs a specific version of ecctl (Elastic Cloud control tool) and cache it on the runner.
Usage
Inputs
Parameter Required Default Value Description version
false
latest
Ecctl tool version such as v1.0.0-beta3
. Ecctl vesion can be found here.Supported Environments: Linux and macOS
Outputs
Parameter Description ecctl-path
ecctl command path Sample Workflow
A specific version of ecctl can be setup by giving an input -
version
like this:- uses: yokawasa/action-setup-ecctl@v0.1.0 with: version: 'v1.0.0-beta3' # default is 'latest' id: setup - run: | ecctl version
The latest version of ecctl will be setup if you don’t give an input like this:
- uses: yokawasa/action-setup-ecctl@v0.1.0 id: setup - run: | ecctl version
Developing the action
Install the dependencies
npm install
Build the typescript and package it for distribution by running ncc
npm run build && npm run pack
Finally push the resutls
git add dist git commit -a -m "prod dependencies" git push origin releases/v0.1.0
Enjoy the action!
-
my old college roommate
A scene at wedding ceremony of my old collage roommate
Jan 18, 2020 at Brooklyn NY
-
Getting Kubernetes Metrics using kubectl
There are various ways to obtain Kubernetes metrics which you can use to visualize, monitor and alert on your metrics. In reality you most likely use managed or unmanaged OSS metrics collection and visualization tools, but in this post, I introduce how to get raw Kubernetes metrics using kubectl.
Kubernetes Raw Metrics via Prometheus metrics endpoint
Many Kubernetes components exposes their metrics via the
/metrics
endpoint, including API server, etcd and many other add-ons. These metrics are in Prometheus format, and can be defined and exposed using Prometheus client libskubectl get --raw /metrics
Sample output - /metrics
APIServiceOpenAPIAggregationControllerQueue1_adds 282663 APIServiceOpenAPIAggregationControllerQueue1_depth 0 APIServiceOpenAPIAggregationControllerQueue1_longest_running_processor_microseconds 0 APIServiceOpenAPIAggregationControllerQueue1_queue_latency{quantile="0.5"} 63 APIServiceOpenAPIAggregationControllerQueue1_queue_latency{quantile="0.9"} 105 APIServiceOpenAPIAggregationControllerQueue1_queue_latency{quantile="0.99"} 126 APIServiceOpenAPIAggregationControllerQueue1_queue_latency_sum 1.4331448e+07 APIServiceOpenAPIAggregationControllerQueue1_queue_latency_count 282663 APIServiceOpenAPIAggregationControllerQueue1_retries 282861 APIServiceOpenAPIAggregationControllerQueue1_unfinished_work_seconds 0 APIServiceOpenAPIAggregationControllerQueue1_work_duration{quantile="0.5"} 59 APIServiceOpenAPIAggregationControllerQueue1_work_duration{quantile="0.9"} 98 APIServiceOpenAPIAggregationControllerQueue1_work_duration{quantile="0.99"} 2003 APIServiceOpenAPIAggregationControllerQueue1_work_duration_sum 2.1373689e+07 APIServiceOpenAPIAggregationControllerQueue1_work_duration_count 282663 ...
Kubernetes Raw Metrics via metrics API
You can access Kubernetes Metrics API via kubectl proxy like this:
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes/<node-name> kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/<namespace-name>/pods/<pod-name>
(ref: feiskyer/kubernetes-handbook)
Outputs via metrics API are unformated JSON, thus it’s good to use
jq
to parse it.Sample output - /apis/metrics.k8s.io/v1beta1/nodes
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes | jq
{ "kind": "NodeMetricsList", "apiVersion": "metrics.k8s.io/v1beta1", "metadata": { "selfLink": "/apis/metrics.k8s.io/v1beta1/nodes" }, "items": [ { "metadata": { "name": "ip-xxxxxxxxxx.ap-northeast-1.compute.internal", "selfLink": "/apis/metrics.k8s.io/v1beta1/nodes/ip-xxxxxxxxxx.ap-northeast-1.compute.internal", "creationTimestamp": "2020-05-24T01:29:05Z" }, "timestamp": "2020-05-24T01:28:58Z", "window": "30s", "usage": { "cpu": "105698348n", "memory": "819184Ki" } }, { "metadata": { "name": "ip-yyyyyyyyyy.ap-northeast-1.compute.internal", "selfLink": "/apis/metrics.k8s.io/v1beta1/nodes/ip-yyyyyyyyyy.ap-northeast-1.compute.internal", "creationTimestamp": "2020-05-24T01:29:05Z" }, "timestamp": "2020-05-24T01:29:01Z", "window": "30s", "usage": { "cpu": "71606060n", "memory": "678944Ki" } } ] }
Sample output - /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/PODNAME
kubectl get --raw /apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/cluster-autoscaler-7d8d69668c-5rcmt | jq
{ "kind": "PodMetrics", "apiVersion": "metrics.k8s.io/v1beta1", "metadata": { "name": "cluster-autoscaler-7d8d69668c-5rcmt", "namespace": "kube-system", "selfLink": "/apis/metrics.k8s.io/v1beta1/namespaces/kube-system/pods/cluster-autoscaler-7d8d69668c-5rcmt", "creationTimestamp": "2020-05-24T01:33:17Z" }, "timestamp": "2020-05-24T01:32:58Z", "window": "30s", "containers": [ { "name": "cluster-autoscaler", "usage": { "cpu": "1030416n", "memory": "27784Ki" } } ] }
See also
- https://github.com/kubernetes/metrics
- feiskyer/kubernetes-handbook
- https://prometheus.io/docs/instrumenting/clientlibs/
- Prometheus format
- https://github.com/yokawasa/kubectl-tips
-
Visual Studio Code Textbook for programmer was published!
-
GitHub Actions - SQLCheck Action
I’ve published a new GitHub Action called SQLCheck Action (View on Marketplace). The action automatically identifies anti-patterns in SQL queries using sqlcheck when PR is requested and comment on the PR if risks are found in the queries.
Usage
Supports
pull_request
event type.Inputs
Parameter Required Default Value Description post-comment
false true Post comment to PR if it’s true token
true ”” GitHub Token in order to add comment to PR risk-level
false 3 Set of SQL anti-patterns to check: 1,2, or 3
- 1 (all anti-patterns, default)
- 2 (only medium and high risk anti-patterns)
- 3 (only high risk anti-patterns)verbose
false false Add verbose warnings to SQLCheck analysis result postfixes
false “sql” List of file postfix to match ( separator: comma ) Sample Workflow
.github/workflows/test.yml
name: sqlcheck workflow on: pull_request jobs: sqlcheck: name: sqlcheck job runs-on: ubuntu-latest steps: - uses: actions/checkout@master - uses: yokawasa/action-sqlcheck@v1.2.1 with: post-comment: true risk-level: 3 verbose: false token: ${{ secrets.GITHUB_TOKEN }}
Enjoy the action!
-
My last day at Microsoft
Today is my last day at Microsoft. About 9 years and 2 months have passed since I joined MS. I’ve had wonderful years filled with various experiences on business.
In the first 4 years, as FAST Search engineer & consultant, I specialized in Fast search and provided customers in Japan and sometimes in South East Asia & South Korea area with proactive consulting & support. For the next 3 years after that, as a part of Azure Solution Architect teams, I provided architectural guidance & design session, PoC and prototyping support, knowledge transfer trainings with Japanease enterprise customers, collaborating with Azure engineering teams, Azure sales teams and many other stakeholders. I also engaged with communities inside/outside Microsoft, participating in Microsoft hosting conferences / industry showcase events, and contributing OSS communities. In the latest 2 years, as a part of global technical SWAT team in enterprise sales organization internally called ‘Global Black Belt, I was responsible for leading technical engagements to win based on solutions leveraging the Microsoft Azure and OSS with a specialization in cloud native application architecture and development such as Microservices, Containers/Serverless, PaaS, DevOps, and so on. Along with my everyday job I had awesome opportunities to speak at conferences and meetups about many technical topics mostly on Cloud Native tech and architectures. It was awesome 9 years and 2 months!!
I would like to extend my sincerest thanks to all the my customers and partners I have worked with so far. I also thank, each one of my colleague and managers who made my journey a memorable one in Microsoft.
I will start a new phase of my career from tomorrow. But it is indeed a small world in our industry. I hope our paths cross again, and it would be great if we may be able to work together again somewhere.
Please reach out to me if you ever want to catch up.
My personal contacts: yokawasa @ linkedin, twitter, facebook & github -
Find the lowest latency Azure regions from your place using azping
azping is a command line tools that help you find the lowest latency Azure Region from your place. It acutally reports median latency to Azure regions. It is a fork of gcping.
What does azping actually evalulate?
azping evalulate the median latecy of http requests to Azure blob storage endpoints located in each of Azure reagions from your place. Number of requests to be made to each region is
5
by default, but it can be changed with-n
parameter that you can give in executing azping command.Here is a list of Azure blob storage endpoints that azping evalulates:
region endpoint eastasia azpingeastasia.blob.core.windows.net/ping southeastasia azpingsoutheastasia.blob.core.windows.net/ping centralus azpingcentralus.blob.core.windows.net/ping eastus azpingeastus.blob.core.windows.net/ping eastus2 azpingeastus2.blob.core.windows.net/ping westus azpingwestus.blob.core.windows.net/ping northcentralus azpingnorthcentralus.blob.core.windows.net/ping southcentralus azpingsouthcentralus.blob.core.windows.net/ping northeurope azpingnortheurope.blob.core.windows.net/ping westeurope azpingwesteurope.blob.core.windows.net/ping japanwest azpingjapanwest.blob.core.windows.net/ping japaneast azpingjapaneast.blob.core.windows.net/ping brazilsouth azpingbrazilsouth.blob.core.windows.net/ping australiaeast azpingaustraliaeast.blob.core.windows.net/ping australiasoutheast azpingaustraliasoutheast.blob.core.windows.net/ping southindia azpingsouthindia.blob.core.windows.net/ping centralindia azpingcentralindia.blob.core.windows.net/ping westindia azpingwestindia.blob.core.windows.net/ping canadacentral azpingcanadacentral.blob.core.windows.net/ping canadaeast azpingcanadaeast.blob.core.windows.net/ping uksouth azpinguksouth.blob.core.windows.net/ping ukwest azpingukwest.blob.core.windows.net/ping westcentralus azpingwestcentralus.blob.core.windows.net/ping westus2 azpingwestus2.blob.core.windows.net/ping koreacentral azpingkoreacentral.blob.core.windows.net/ping koreasouth azpingkoreasouth.blob.core.windows.net/ping francecentral azpingfrancecentral.blob.core.windows.net/ping australiacentral azpingaustraliacentral.blob.core.windows.net/ping uaenorth azpinguaenorth.blob.core.windows.net/ping southafricanorth azpingsouthafricanorth.blob.core.windows.net/ping NOTE All blob storage endpoints are created with the following scripts (Just in case I leave the procedures):
$ git clone https://github.com/yokawasa/azping.git $ cd setup # Edit RESOURCE_GROUP and REGION_LIST variables in env.sh $ vi env.sh # Read variables as enviroment variables $ source env.sh # Execute the following script that execute the following| # (1) Create resource group for azping # (2) Create blob storage accounts in each of Azure regions # (3) Create $root container and upload ping file to the container # (4) Check accessibility to all blob storage endpoints $ ping-entrypoint.sh
How to install
Linux 64-bit|https://azpingrelease.blob.core.windows.net/azping_linux_amd64
$ curl https://azpingrelease.blob.core.windows.net/azping_linux_amd64 > azping && chmod +x azping
Mac 64-bit|https://azpingrelease.blob.core.windows.net/azping_darwin_amd64
$ curl https://azpingrelease.blob.core.windows.net/azping_darwin_amd64 > azping && chmod +x azping
Windows 64-bit|https://azpingrelease.blob.core.windows.net/azping_windows_amd64
# use WSL-bash $ curl https://azpingrelease.blob.core.windows.net/azping_windows_amd64 > azping && chmod +x azping
Or, you can always build the binary from the source code like this:
$ git clone https://github.com/yokawasa/azping.git $ cd azping $ make $ tree bin bin ├── azping_darwin_amd64 ├── azping_linux_amd64 └── azping_windows_amd64
Usage
$ azping [options...] Options: -n Number of requests to be made to each region. By default 5; can't be negative. -c Max number of requests to be made at any time. By default 10; can't be negative or zero. -t Timeout. By default, no timeout. Examples|"500ms", "1s", "1s500ms". -top If true, only the top region is printed. -csv CSV output; disables verbose output. -v Verbose output.
Screenshot
Here is an output of azping when I executed azping from my home in Tokyo
Enjoy azping!
-
Unofficial tips for CKA and CKAD exams
I’ve taken both Certified Kubernetes Administrator (CKA) and Certified Kubernetes Application Developer (CKAD) exams in the past 2 weeks and fortunately passed both. This is a blog article on tips for both exams based on my experiences.
About the exam and its curriculum
CKA focus on managing and operating kubernetes cluster including troubleshooting while CKAD forcus on managing and deploying applicaionts to kubernetes cluster.
It’s very important to read and understand the exam curriculum and their relevant pages on kubernetes.io as all topics you’re expected to understand are inlcuded in the curriculum and they are definitly going to be on the exam.
Tips for the exams
- Read and understand the exam curriculum and their relevant pages on kubernetes.io. You are allowed to look up the following sites during the exam
- For both CKA and CKAD: the following are books that I found useful for CKA and CKAD. They are defenitly helpful to understand how to manage and operate the kubernetes cluster. Pick one or two that you think good fit and read through:
- Book: Kubernetes: Up and Running
- Book: Managing Kubernetes (Free PDF by Heptio is here)
- Book(日本語): Kubernetes完全ガイド
- Book(日本語): しくみがわかるKubernetes Azureで動かしながら学ぶコンセプトと実践知識
- Book(日本語): Kubernetes実践入門 プロダクションレディなコンテナ&アプリケーションの作り方
- For CKA: learn how to install, configure & validate kubernetes cluster. These are good materials to go through:
- For CKA: learn how to troubleshoot the cluster. I recommend to read the following pages in kubernetes.io
- For CKA: these below are Github repo that I though very useful for CKA exam preps:
- For CKAD: these below are Github repo that I thought very very useful for CKAD exam preps:
- For both: it’s very important to know a quick way to achieve goals by using kubectl. You can lookup kubernetes.io during the exam but it’s always good to know shortcut ways as the exam time is limited (CKA = 3hrs / CKAD = 2hrs)
- Kubectl Cheat Sheet
- Creating template YAML using kubectl
dry-run
and edit it instead of creating YAML from scratch# Pod template $ kubectl run nginx --image=nginx --restart=Never --dry-run -o yaml # Deployment template $ kubectl run nginx --image=nginx --dry-run -o yaml # Servcie template $ kubectl expose deployment nginx --type=NodePort --port 8080 --dry-run -o yaml # [NOTE1] # You can change resource to release by changing --restart option: # kind | option # --------------------------------------------- # deployment | none # pod | --restart=Never # job | --restart=OnFailure # cronjob | --schedule='cron format(0/5 * * * ? など)' # [NOTE2] # In case that kubectl run will be deprecated in the future, $ kubectl create deployment nginx --image=nginx --dry-run -o yaml
- Tips during the exam
- ID: Candidates are required to provide government-issued photo identification before the Exam (Read Candidate Handbook). For non-english language folks,
Passport
would be the best! - Testing Room: you need to prepare a room for testing which must be quiet, private and well lit.
- Virtual screen: you can virtual screen like tmux and screen. It would be very helpful to use multple screens like using one for deploying kuberenetes resources while using the other one for looking up kuberentes resource state and logs. For example, I’m a tmux user, and added the following
.tmux.conf
before starting tackling with questions:set-option -g prefix C-z
- Command alias: Setting up alias definitly help you to shorten the time you need to type in commands. For examples,
alias k=kubectl
- Time management: Don’t spend too much time on difficult questions. Try to finish all easy questions first and spend the rest for difficult ones. You don’t have to beat everything to pass the exam!! - A score of at least
74%
forCKA
and66%
forCKAD
to pass the exam - Searchability: you can use and search the kubernetes.io pages. Even if you have no idea on questions on the exam, don’t give up and try to type some keywords to search the kubernetes.io pages. You may be lucky enough to find some hints or right answers on the site.
- ID: Candidates are required to provide government-issued photo identification before the Exam (Read Candidate Handbook). For non-english language folks,
Final comments
Again, the most important tip for both exams is to read and understand the exam curriculum and all relevant pages on kubernetes.io. You don’t have to memorize but understand them. Event if you don’t come up with exact command options or kubernetes resource objects for questions in the exam, you can lookup and point to appropriate pages during the exam. In addition, get familiar with basic linux commands and cluster operations and management commands. If you have any questions, send DM to me @yokawasa.
Good luck with your exams!
ps. Here are my Certificate IDs
-
Easy way to SSH into Azure Kubernetes Service cluster node VMs
This is an article on how you can SSH into Azure Kubernetes Service (AKS) cluster node VMs using kubectl-plugin-ssh-jump.
Motivation
I wanted to SSH into Azure Kubernetes Service (AKS) cluster node VMs, then looking up azure docs I found a relevant page - Connect with SSH to Azure Kubernetes Service (AKS) cluster nodes for maintenance or troubleshooting. But when I first saw this procedure, I thought this was very troublesome. Lazy person like me couldn’t accept going thourgh all the steps just to SSH into AKS cluster nodes VMs. This is why I decided to create kubectl-plugin-ssh-jump, a kubectl plugin to SSH into Kubernetes nodes using a SSH jump host Pod.
AKS node access control and SSH access strategy
By default, AKS nodes are not exposed to the internet, and they are completely isolated to their own virtual network. This is why I took a strategy to go through a jump host Pod to connect to the Kubernetes nodes. I believe this is pretty a general strategy in dealing with firewalling, access privileges, etc.
Regarding SSH key with which you access the nodes via SSH, you need to use the SSH key that you chosen in creating your AKS cluster. Or in the case that you lose the key, you can update SSH Key by using az command like this (See this for more detail):
az vm user update \ --resource-group myResourceGroup \ --name myVM \ --username azureuser \ --ssh-key-value ~/.ssh/id_rsa.pub
As an additional security enhancement, you can configure Access Control(IAM) on the AKS cluster to set permissions on the nodes on who can access them. Please see What is role-based access control (RBAC)? for the detail on RBAC.
SSH into AKS node VMs using kubectl-plugin-ssh-jump
Pre-requistes
This plugin needs the following programs:
- ssh(1)
- ssh-agent(1)
Installation
Install through krew
This is a way to install kubectl-ssh-jump through krew. After installing krew by following this, you can install kubectl-ssh-jump like this:
$ kubectl krew install ssh-jump
Expected output would be like this:
Updated the local copy of plugin index. Installing plugin: ssh-jump CAVEATS: \ | This plugin needs the following programs: | * ssh(1) | * ssh-agent(1) | | Please follow the documentation: https://github.com/yokawasa/kubectl-plugin-ssh-jump / Installed plugin: ssh-jump
Once it’s installed, run:
$ kubectl plugin list The following kubectl-compatible plugins are available: /Users/yoichika/.krew/bin/kubectl-krew /Users/yoichika/.krew/bin/kubectl-ssh_jump $ kubectl ssh-jump
Manual Installation
Install the plugin by copying the script in the $PATH of your shell.
# Get source $ git clone https://github.com/yokawasa/kubectl-plugin-ssh-jump.git $ cd kubectl-plugin-ssh-jump $ chmod +x kubectl-ssh-jump # Add kubeclt-ssh-jump to the install path. $ sudo cp -p kubectl-ssh-jump /usr/local/bin
Once in the $PATH, run:
$ kubectl plugin list The following kubectl-compatible plugins are available: /usr/local/bin/kubectl-ssh-jump $ kubectl ssh-jump
How to use
Usage
Usage: kubectl ssh-jump <dest_node> [options] Options: <dest_node> Destination node IP -u, --user <sshuser> SSH User name -i, --identity <identity_file> Identity key file -p, --pubkey <pub_key_file> Public key file --skip-agent Skip automatically starting SSH agent and adding SSH Identity key into the agent before SSH login (=> You need to manage SSH agent by yourself) --cleanup-agent Clearning up SSH agent at the end The agent is NOT cleaned up in case that --skip-agent option is given --cleanup-jump Clearning up sshjump pod at the end Default: Skip cleaning up sshjump pod -h, --help Show this message
Option parameters Cache
username
,identity
,pubkey
options are cached, therefore you can omit these options afterward. The options are stored in a file named$HOME/.kube/kubectlssh/options
$ cat $HOME/.kube/kubectlssh/options sshuser=azureuser identity=/Users/yokawasa/.ssh/id_rsa_k8s pubkey=/Users/yokawasa/.ssh/id_rsa_k8s.pub
SSH Agent (ssh-agent)
The plugin automatically check if there are any
ssh-agents
started running by the plugin, and startsssh-agent
if it doesn’t find anyssh-agent
running and adds SSH Identity key into the agent before SSH login. If the command find that ssh-agent is already running, it doesn’t start a new agent, and re-use the agent. Add--cleanup-agent
option if you want to kill the created agent at the end of command.In addtion, add
--skip-agent
option if you want to skip automatic startingssh-agent
. This is actually a case where you already have ssh-agent managed or you want to manually start the agent.Examples
Show all node list. Simply executing
kubectl ssh-jump
gives you the list of destination nodes as well as command usage$ kubectl ssh-jump Usage: kubectl ssh-jump <dest_node> [options] Options: <dest_node> Destination node IP -u, --user <sshuser> SSH User name -i, --identity <identity_file> Identity key file -p, --pubkey <pub_key_file> Public key file --skip-agent Skip automatically starting SSH agent and adding SSH Identity key into the agent before SSH login (=> You need to manage SSH agent by yourself) --cleanup-agent Clearning up SSH agent at the end The agent is NOT cleaned up in case that --skip-agent option is given --cleanup-jump Clearning up sshjump pod at the end Default: Skip cleaning up sshjump pod -h, --help Show this message Example: .... List of destination node... Hostname aks-nodepool1-18558189-0 aks-nodepool1-18558189-1 aks-nodepool1-18558189-2
Then, SSH into a node
aks-nodepool1-18558189-0
with options like:- usernaem:
azureuser
- identity:
~/.ssh/id_rsa_k8s
- pubkey:
~/.ssh/id_rsa_k8s.pub
)$ kubectl ssh-jump aks-nodepool1-18558189-0 \ -u azureuser -i ~/.ssh/id_rsa_k8s -p ~/.ssh/id_rsa_k8s.pub
As explained in usage secion,
username
,identity
,pubkey
options are cached, therefore you can omit these options afterward.$ kubectl ssh-jump aks-nodepool1-18558189-0
You can pass the commands to run in the destination node like this (Suppose that
username
,identity
,pubkey
options are cached):echo "uname -a" | kubectl ssh-jump aks-nodepool1-18558189-0 (Output) Linux aks-nodepool1-18558189-0 4.15.0-1035-azure #36~16.04.1-Ubuntu SMP Fri Nov 30 15:25:49 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
You can clean up sshjump pod at the end of the command with
--cleanup-jump
option, otherwise, the sshjump pod stay running by default.$ kubectl ssh-jump aks-nodepool1-18558189-0 \ -u azureuser -i ~/.ssh/id_rsa_k8s -p ~/.ssh/id_rsa_k8s.pub \ --cleanup-jump
You can clean up ssh-agent at the end of the command with
--cleanup-agent
option, otherwise, the ssh-agent process stay running once it’s started.$ kubectl ssh-jump aks-nodepool1-18558189-0 \ -u azureuser -i ~/.ssh/id_rsa_k8s -p ~/.ssh/id_rsa_k8s.pub \ --cleanup-agent
You can skip starting
ssh-agent
by giving--skip-agent
. This is actually a case where you already have ssh-agent managed. Or you can start new ssh-agent and add an identity key to the ssh-agent like this:# Start ssh-agent manually $ eval `ssh-agent` # Add an arbitrary private key, give the path of the key file as an argument to ssh-add $ ssh-add ~/.ssh/id_rsa_k8s # Then, run the plugin with --skip-agent $ kubectl ssh-jump aks-nodepool1-18558189-0 \ -u azureuser -i ~/.ssh/id_rsa_k8s -p ~/.ssh/id_rsa_k8s.pub \ --skip-agent # At the end, run this if you want to kill the current agent $ ssh-agent -k
-
Set of Envoy Proxy features demos
Set of demos to demonstrate Envoy Proxy features
HTTP Routing: Simple Match Routing
All traffic is routed by the
front envoy
to theservice containers
. Internally the traffic is routed to the service envoys, then the service envoys route the request to the flask app via the loopback address. In this demo, all traffic is routed to the service envoys like this:- A request (path
/service/blue
& port8000
) is routed toservice_blue
- A request (path
/service/green
& port8000
) is routed toservice_green
- A request (path
/service/red
& port8000
) is routed toservice_red
Key definition 1 -
virtual_hosts
in front-envoy.yamlvirtual_hosts: - name: backend domains: - "*" routes: - match: prefix: "/service/blue" route: cluster: service_green - match: prefix: "/service/blue" route: cluster: service_blue - match: prefix: "/service/red" route: cluster: service_red
Key definition 2 -
clusters
in front-envoy.yamlclusters: - name: service_blue connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_blue port_value: 80 - name: service_green connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_green port_value: 80 - name: service_red connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_red port_value: 80
To continue, go to github
HTTP Routing: Routing based on Header Condition
Key definition 1 -
virtual_hosts
in front-envoy.yamlvirtual_hosts: - name: backend domains: - "*" routes: - match: prefix: "/service/blue" headers: - name: "x-canary-version" exact_match: "service_green" route: cluster: service_green - match: prefix: "/service/blue" route: cluster: service_blue - match: prefix: "/service/red" route: cluster: service_red
Key definition 2 -
clusters
in front-envoy.yamlclusters: - name: service_blue connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_blue port_value: 80 - name: service_green connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_green port_value: 80 - name: service_red connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_red port_value: 80
To continue, go to github
HTTP Routing: Blue Green Traffic Splitting
Key definition 1 -
virtual_hosts
in front-envoy.yamlvirtual_hosts: - name: backend domains: - "*" routes: - match: prefix: "/service/blue" route: weighted_clusters: clusters: - name: service_green weight: 10 - name: service_blue weight: 90 - match: prefix: "/service/red" route: cluster: service_red
Key definition 2 -
clusters
in front-envoy.yamlclusters: - name: service_blue connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_blue port_value: 80 - name: service_green connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_green port_value: 80 - name: service_red connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service_red port_value: 80
To continue, go to github
Fault Injection
Fault injection is a technique for improving the coverage of a test by introducing faults to test code paths, in particular error handling code paths, that might otherwise rarely be followed. The
filter
( http_filters in the demo ) can be used to injectdelays
andabort
requests with user-specified error codes.Front-proxy configurations are the same as the ones in HTTP Routing: Simple Match Routing. Differences from HTTP Routing: Simple Match Routing are the following 2 fault injections:
- Fault injection
abort
(50% of requests will be aborted with 503 error code) for the requests toservice_red
- Fault injection
delay
(50% of requests will be 10 seconds delayed) for the requests toservice_blue
Key definition 1 -
http_filters
in service-envoy-fault-injection-abort.yamlhttp_filters: - name: envoy.fault config: abort: http_status: 503 percentage: numerator: 50 denominator: HUNDRED
For
numerator
anddenominator
ofpercentage
, see type.FractionalPercentKey definition 2 -
http_filters
in service-envoy-fault-injection-delay.yamlhttp_filters: - name: envoy.fault config: delay: type: fixed fixed_delay: 10s percentage: numerator: 50 denominator: HUNDRED
For
fixed_delay
andpercentage
of delay injection, see config.filter.fault.v2.FaultDelayTo continue, go to github
Circuit Breaker
Circuit Breaking lets you configure failure thresholds that ensure safe maximums after which these requests stop. This allows for a more graceful failure, and time to respond to potential issues before they become larger.
- Circuit Breaker is configured in
service_red
such that Circuit Breaker will be triggered with the following conditions:- Envoy makes more than
max connection#:1
- Envoy makes more than
max parallel requests#:1
- Envoy makes more than
Key definition -
clusters
in service-envoy-circuitbreaker.yamlclusters: - name: local_service connect_timeout: 0.25s type: strict_dns lb_policy: round_robin circuit_breakers: thresholds: max_connections: 1 max_pending_requests: 1 max_requests: 1 hosts: - socket_address: address: 127.0.0.1 port_value: 8080
For the detail of
circuit_breakers
configuration, see cluster.CircuitBreakersTo continue, go to github
Timeouts and Retries
Front-proxy configurations are the same as the ones in HTTP Routing: Simple Match Routing. Differences from HTTP Routing: Simple Match Routing are the following 2 additional behaviors:
Timeouts
(5 seconds) for the request toservice_blue
Retries
that Envoy will attempt to do ifservice_red
responds with any 5xx response code
For Service Containers,
delay
fault injection andabort
fault injection are configured inservice_blue
andservice_red
respectively (which are the same configuration as the ones in Fault Injection Demo)Key definition -
virtual_hosts
in front-envoy.yamlvirtual_hosts: - name: backend domains: - "*" routes: - match: prefix: "/service/blue" route: cluster: service_blue timeout: 5s - match: prefix: "/service/green" route: cluster: service_green - match: prefix: "/service/red" route: cluster: service_red retry_policy: retry_on: "5xx" num_retries: 3 per_try_timeout: 5s
timeout
: (Duration) Specifies the timeout for the route. If not specified, the default is 15s. For more detail, seetimeout
section in RouteActionretry_policy
indicates the retry policy for all routes in this virtual host. For more detail on retry_policy, see route.RetryPolicy
To continue, go to github
- A request (path
-
Quick Start with Azure Functions V2 Python (Preview)
Today (Sept 25, 2018 JST), Azure Functions supports Python development using Python 3.6 on the Functions v2 (cross-platform) runtime. You can now use your Python code and dependencies on Linux-based Functions. This is an article on quick start with Azure Functions V2 Python (Preview) showing how you can quickly start Python function development on Azure Function V2 runtime.
1. Prerequisites for Buidling & Testing Locally
- Python 3.6 (For Python function apps, you have to be running in a
venv
) - Azure Functions Core Tools 2.0.3 or later
Prerequisite 1 - Python version
This is how you switch your python version using
venv
.First of all, install Python 3.6 if you don’t have on your local environemnt.
$ python3.6 -V Python 3.6.1
Then, to build and test Python function with
Azure Functions Core Tools
(you’ll install after this), you need to setup a Python 3.6 virtual environemnt usingvenv
(NOT, pyenv or some other virtual env tools).$ python -V Python 2.7.1 # create and activate virutal environemnt named "venv3.6" $ python3.6 -m venv venv3.6 $ source venv3.6/bin/activate $ Python -V Python 3.6.1
[NOTE] As virtualenv (venv) was included in Python3.3, you don’t need to install venv separately. It’s already in your Python 3.6
Prerequisite 2 - Azure Functions Core Tools
You need to install
azure-functions-core-tools
version2.0.3
or later for buiding & testing Python functions on Azure Functions V2 runtime.# Check current package version (only if you already have azure-functions-core-tools installed) $ func --version 2.0.1-beta.35 $ npm list -g --depth=0 |grep azure-functions-core-tools ├── azure-functions-core-tools@2.0.1-beta.35 # Check available package versions $ npm info azure-functions-core-tools versions '2.0.1-beta.31', '2.0.1-beta.32', '2.0.1-beta.33', '2.0.1-beta.34', '2.0.1-beta.35', '2.0.1-beta.37', '2.0.1-beta.38', '2.0.1-beta.39', '2.0.1-beta.23-1', '2.0.1-beta1.15', '2.0.2', '2.0.3' ] # Install speicific package version - 2.0.3 $ npm install -g azure-functions-core-tools@2.0.3 $ func --version 2.0.3
2. Create Python Function and run locally
2-1. Create Python Functions Project
Create a local Python Functions project -
v2projects
$ func init v2projects --worker-runtime python Installing wheel package Installing azure-functions==1.0.0a4 package Installing azure-functions-worker==1.0.0a4 package Running pip freeze Writing .gitignore Writing host.json Writing local.settings.json Writing /Users/yoichika/dev/github/azure-functions-python-samples/v2projects/.vscode/extensions.json
A new folder named
v2projects
is created. Then, change directory to this folder$ cd v2projects
2-2. Create a python function
Check function template list
$ func templates list C# Templates: Blob trigger Cosmos DB trigger Durable Functions activity Durable Functions HTTP starter Durable Functions orchestrator Event Grid trigger Event Hub trigger HTTP trigger Outlook message webhook creator Outlook message webhook deleter Outlook message webhook handler Outlook message webhook refresher Microsoft Graph profile photo API Queue trigger SendGrid Service Bus Queue trigger Service Bus Topic trigger Timer trigger JavaScript Templates: Blob trigger Cosmos DB trigger Event Grid trigger HTTP trigger Queue trigger SendGrid Service Bus Queue trigger Service Bus Topic trigger Timer trigger Python Templates: Blob trigger Cosmos DB trigger Event Grid trigger Event Hub trigger HTTP trigger Queue trigger Service Bus Queue trigger Service Bus Topic trigger Timer trigger
Create a python funciton with “HTTP trigger” template
$ func new --language Python --template "HTTP trigger" --name HttpTriggerPython Select a template: HTTP trigger Function name: [HttpTriggerPython] Writing /Users/yoichika/dev/github/azure-functions-python-samples/v2projects/HttpTriggerPython/sample.dat Writing /Users/yoichika/dev/github/azure-functions-python-samples/v2projects/HttpTriggerPython/__init__.py Writing /Users/yoichika/dev/github/azure-functions-python-samples/v2projects/HttpTriggerPython/function.json The function "HttpTriggerPython" was created successfully from the "HTTP trigger" template.
2-3. Local Testing
Run the Functions host locally.
$ func host start
Then, send a test requst to the given endpoint for the HttpTrigger function
$ curl http://localhost:7071/api/HttpTriggerPython?name=AzureFunctionV2 Hello AzureFunctionV2!
3. Create Linux FunctionApps (Preview Consumption App)
Now you create Functions App to deploy and run your Python functions on Azure. You actually need Linux V2 Function Apps as publishing Python functions is only supported for Linux Function Apps. So let’s create the Azure Functions Linux Consumption App (which is in preview as of today Sept 25, 2018 JST).
3-1. Whitelist request for accessing the Azure Functions Linux Consumption (preview)
As guided in Azure Functions on Linux Preview, you need to email linuxazurefunctions at Microsoft dot com with your Azure subscription ID to get your ID whitelisted to access the Azure Functions Linux Consumption (Preview). [NOTE] This is only needed during its preview preriod.
3-2. Install the Azure CLI extension for the Azure Functions Linux Consumption preview
As a prerequisite, you need to install the Azure CLI extension for the Azure Functions Linux Consumption preview. Here is how you do:
$ curl "https://functionscdn.azureedge.net/public/docs/functionapp-0.0.1-py2.py3-none-any.whl" \ -o functionapp-0.0.1-py2.py3-none-any.whl $ az extension add --source functionapp-0.0.1-py2.py3-none-any.whl
For more detail, see this doc
3-3. Create a resource group
RESOURCE_GROUP="RG-azfuncv2" REGION="eastus" az group create --name $RESOURCE_GROUP --location $REGION
3-4. Create an Azure Storage Account
STORAGE_ACCOUNT="azfuncv2linuxstore" az storage account create --name $STORAGE_ACCOUNT \ --location $REGION \ --resource-group $RESOURCE_GROUP \ --sku Standard_LRS
3-5. Create a Empty Function App on Linux (Consumption Plan)
Give your function app name to
APP_NAME
variable, and execute az command like this.APP_NAME="yoichikaazfuncv2linux001" az functionapp createpreviewapp --name $APP_NAME \ --resource-group $RESOURCE_GROUP \ --storage-account $STORAGE_ACCOUNT \ -l $REGION \ --runtime python \ --is-linux (output) Your Linux, cosumption plan, function app 'yoichikaazfuncv2linux001' has been successfully created but is not active until content is published usingAzure Portal or the Functions Core Tools.
[NOTE] The Function App name needs to be unique across all apps in Azure.
Now you’re ready to publish your functions to the App!
4. Publish the Python Function
You publish the Python functions to the function app ( named
yoichikaazfuncv2linux001
here )# func azure functionapp publish <app_name> $ func azure functionapp publish yoichikaazfuncv2linux001 --force Getting site publishing info... pip download -r /Users/yoichika/dev/github/azure-functions-python-samples/v2projects/requirements.txt --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerry44_fwz pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g azure_functions_worker==1.0.0a4 pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g azure_functions==1.0.0a4 pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g protobuf==3.6.1 pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g grpcio_tools==1.14.2 pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g setuptools==40.4.3 pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g grpcio==1.14.2 pip download --no-deps --only-binary :all: --platform manylinux1_x86_64 --python-version 36 --implementation cp --abi cp36m --dest /var/folders/mn/xw3hp_854lvb5yr2m_00s7sm0000gn/T/azureworkerpcdk1t4g six==1.11.0 Preparing archive... Uploading content... Upload completed successfully. Deployment completed successfully. Removing 'WEBSITE_CONTENTSHARE' from 'yoichikaazfuncv2linux001' Removing 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' from 'yoichikaazfuncv2linux001' Syncing triggers...
[NOTE]
- if you run
func azure functionapp publish
without--force
opiton, you’ll come up with the following the message:Your app is configured with Azure Files for editing from Azure Portal. To force publish use --force. This will remove Azure Files from your app.
- Please be noted that when deployging from
func
command( ie, running from a package), the file system in Azure Function App is read-only and no changes can be made to the files. To make any changes update the content in your zip file and WEBSITE_RUN_FROM_PACKAGE app setting.
Looks like pulishing has completed successfully, so let’s access to the function on Azure
$ curl https://yoichikaazfuncv2linux001.azurewebsites.net/api/HttpTriggerPython?name=AzureFunctionV2 Hello AzureFunctionV2!
Enjoy Azure Functions V2 Python!
LINKS
- Python 3.6 (For Python function apps, you have to be running in a
-
Accessing RBAC enabled Kubernetes Dashboard
This is an article on how you can configure Service Account and RoleBinding in order to make Dashbaord work. As of release Kubernetes v1.7, Dashboard no longer has full admin privileges granted by default. All the privileges are revoked and only minimal privileges granted, that are required to make Dashboard work. With default priviledge, you’ll see the following errors showed up on the Dashboard.
[Azure Kubernetes Service (AKS)] RBAC is enabled by default
Since Azure CLI version 2.0.40, RBAC is enabled by default. As you can see in the Azure command help, your cluster is RBAC enabled unless you specify
--disable-rbac
during the creation of the cluster.$ az --version azure-cli (2.0.43) $ az aks create --help --disable-rbac : Disable Kubernetes Role-Based Access Control. --enable-rbac -r [Deprecated] : Enable Kubernetes Role-Based Access Control. Default: enabled. Argument 'enable_rbac' has been deprecated and will be removed in a future release. Use '--disable-rbac' instead.
Option 1: Access to Dashboard with your Service Account
In option 1, I introduce how to give priviledge your Service Account and access to the Dashboard with the account. Actually there are a couple of authorization options, and here I introduce how to authorize with Bear Token
[NOTE] According to this,
As of release 1.7 Dashboard supports user authentication based on:
- Authorization: Bearer
header passed in every request to Dashboard. Supported from release 1.6. Has the highest priority. If present, login view will not be shown. - Bearer Token that can be used on Dashboard login view.
- Username/password that can be used on Dashboard login view (Disabled by default)
- Kubeconfig file that can be used on Dashboard login view
1-1. Create your Service Account for Dashboard access
First of all, create your Service Account
my-admin-user
like this:$ kubectl create serviceaccount my-admin-user -n kube-system
Or you can create the Service Account with the following YAML
my-sa.yaml
and deploying it withkubectl create -f my-sa.yaml
:# my-sa.yaml apiVersion: v1 kind: ServiceAccount metadata: name: my-admin-user namespace: kube-system
Check if your Service Account (
my-admin-user
) has been added.$ kubectl get sa -n kube-system NAME SECRETS AGE addon-http-application-routing-external-dns 1 9d addon-http-application-routing-nginx-ingress-serviceaccount 1 9d attachdetach-controller 1 9d certificate-controller 1 9d clusterrole-aggregation-controller 1 9d cronjob-controller 1 9d daemon-set-controller 1 9d default 1 9d deployment-controller 1 9d disruption-controller 1 9d endpoint-controller 1 9d generic-garbage-collector 1 9d heapster 1 9d horizontal-pod-autoscaler 1 9d job-controller 1 9d kube-dns 1 9d kube-proxy 1 9d kube-svc-redirector 1 9d kubernetes-dashboard 1 9d my-admin-user 1 15s namespace-controller 1 9d node-controller 1 9d persistent-volume-binder 1 9d pod-garbage-collector 1 9d pv-protection-controller 1 9d pvc-protection-controller 1 9d replicaset-controller 1 9d replication-controller 1 9d resourcequota-controller 1 9d route-controller 1 9d service-account-controller 1 9d service-controller 1 9d statefulset-controller 1 9d ttl-controller 1 9d tunnelfront 1 9d
1-2. Binding the role cluster-admin to the Service Account
Create a
ClusterRoleBinding
which gives the rolecluster-admin
(= full admin priviledge) to the ServiceAccountmy-admin-user
$ kubectl create clusterrolebinding my-admin-user -n kube-system --clusterrole=cluster-admin --serviceaccount=kube-system:my-admin-user
Or you can grant the priviledges with the following YAML
my-sa-binding.yaml
and deploying it withkubectl create -f my-sa-binding.yaml
:# my-sa-binding.yaml apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: my-admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: my-admin-user namespace: kube-system
1-3. Authentication Option - Give Bear Token at Dashboard login view
1-3-1. Get the Token of the ServiceAccount
$ kubectl get secret $(kubectl get serviceaccount my-admin-user -n kube-system -o jsonpath="{.secrets[0].name}") -o jsonpath="{.data.token}" -n kube-system | base64 --decode
Or you can obtain the token step by step like this:
# Get secret name for my-admin-user $ kubectl get serviceaccount my-admin-user -n kube-system -o yaml apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2018-08-11T06:53:34Z name: my-admin-user namespace: kube-system resourceVersion: "1075968" selfLink: /api/v1/namespaces/kube-system/serviceaccounts/my-admin-user uid: 44142169-9d33-11e8-b7d0-de454880a5dc secrets: - name: my-admin-user-token-nzp4f # Get secret string and base64 decoded it $ kubectl get secret my-admin-user-token-nzp4f -n kube-system -o jsonpath="{.data.token}" | base64 --decode eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJteS1hZG1pbi11c2VyLXRva2VuLW56cDRmIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Im15LWFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI0NDE0MjE2OS05ZDMzLTExZTgtYjdkMC1kZTQ1NDg4MGE1ZGMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06bXktYWRtaW4tdXNlciJ9.2ulwCWd7MOnQjoecAY2NoleIxcHD8tda97ud3cK-kHWmdCodAejvddA4YjYozzBu2bWNA83aVTvKAn5-Uv1DC47U5FPh2LXAXNPXn4PyrdLO7TFZdHYmkvUgJKsg25vJvJmsWF9eQOinjjh_g16aGgdxrWz0NGJz5d1eE5GDP5NXXTTgxXlD_GFQduhlq8kc89dhpDUXMYe60-KzZvNaQhIskPsnxHMix1JrHEdtfciFhHRb2CBNjPWfcg455NGoS9S-k0qTfoIHYJC627p75E8TGqyTIa8TSg8vaif4XWgeg_OZWqEIGHTIrhEAGO4ElFijdZuzAg2-v9BGWe8i4q1i70ca5CwReJTG8t13eeOoEkq--VbhDAMY6rxmx-hi9dwf-zjsD233MdHJLh1yRi0eo_k5ov7fwDDsLQXeCTBIjSAzorvXseWr5m9sQ7yREbjDXCOsHbYo5xNV5ii-yOlxYyiqPxZZnnSwzllj1lwPDLSL0MyxkR9siF52vbkNDe6qdYYMqPtA-jTMIw_iLlB-WeN1Fx8423c4x5wV6IGPJZFuOYZhB0ra4jfRSS39vesaNodW8RjHUiuOSVA8_j-DxwOxa8prynALFWGswSMy6PfVQydouU6vammeqPBel9-IqBeTXY-57YumELG1PdcOcxdrBCZUlxBvJWbItxA
1-3-2. Give Bear Token at Dashboard login view
Now that you have a bear token that you need to grant the full priviledges to your Service Account, let’s access to the Dashboard login view.
First of all, create a proxy to the dashboard:
$ kubectl proxy Starting to serve on 127.0.0.1:8001
Then, access to the Dashboard login page:
$ open http://localhost:8001/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy/#!/login
Or if it’s on Azure, you can leverage Azure CLI command to access the Dashboard like this:
$ az aks browse --resource-group <RESOURCE_GROUP> --name <CLUSTER_NAME> $ open http://127.0.0.1:8001/#!/login
You will see the following Dashboard login view. Choose
Token
option and enter the bear token you got above. You will be able to access and operate with the Dashboard without any errors.Easy login by giving Authorization header using Browser extention
As introduced in here, install Requestly browser plugin and configure to make Dashboard use authorization header. You simply need to configure the plugin to pass the following header in accessing the dashboard:
Authorization: Bearer <token>
HERE is the example screen shot:
Option2: Granting admin privileges to Dashboard’s Service Account
In Option 2, I introduce how to give full privilege (role:
cluster-admin
) to the Dashboard’s Service Accountkubernetes-dashboard
. With this option, you can skip the authorization process that you do in the option 1 to access Dashboard. However, as mentioned here, granting admin privileges to Dashboard’s Service Account might be a security risk.First of all, create a
ClusterRoleBinding
which gives the rolecluster-admin
(= full admin priviledge) to the ServiceAccountkubernetes-dashboard
$ kubectl create clusterrolebinding kubernetes-dashboard -n kube-system --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard
Or you can do the same with the following YAML
dashboard-sa-binding.yaml
and deploying it withkubectl create -f dashboard-sa-binding.yaml
:# dashboard-sa-binding.yaml apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard labels: k8s-app: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kube-system
Finally, access to the Dashboard. You’ll be able to access and operate without any errors.
LINKS
- Authorization: Bearer
-
Moving to Jekyll based Github page
I’ve moved my blog site from Wordpress to Jekyll based Github page. There are a few reasons for this:
- I wanted to manage my blog data on Github
- I wanted to switch from HTML based to Markdown
- I wanted more static approach like generating once, not dynamically rendering for every request (for performance reason)
After a few minutes of googling, I came up with Jekyll and found it much easier to manage my blog data with Jekyll than with Wordpress. I love Jekyll’s simplicity. For the one who want to do the same migration, I’d like to share memo on how I migrated the blog site from Wordpress to Jekyll based Github page.
What to do (What I’ve done)
- [ENV] Wordpress is running on Ubuntu 16.04, and I work on all migration works on MacOS (10.13.5)
- Importing my posts from a self-hosted Wordpress
- Install jekyll-import ruby gem and all additional packages needed to import my posts from a self-hosted Wordpress
- Import my posts from the Wordpress
- Convert HTML files to Markdown format files (including manual works)
- Publish the site uisng Jekyll and Github Pages
- Check ruby and github-pages version used in Github page, and install the same github-pages gem on the same ruby version
- Run Jekyll locally and verify the site content
- Create Github project for hosting the site
- Publish the site to Github uisng git
- Setup Custom domain
- Tips
Importing my posts from a self-hosted Wordpress
Install ruby gem packages to import posts from Wordpress
First, check ruby version as jekyll require >
ruby-2.X
, and upgrade its version if it’s not > ruby-2.X (I userbenv
to manage multiple ruby versions on MacOS)$ ruby --version ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin17]
Install
jekyll-import
ruby gem and all additional packages needed to import my posts from a self-hosted Wordpress$ gem install jekyll-import # Additional packages for importing from Wordpress $ gem install sequel $ gem install unidecode $ gem install htmlentities $ gem install mysql2
Import my posts from the Wordpress
Run the following command to import my posts from the hosted Wordpress. Make sure that MySQL server used in Wordpress is accessible
ruby -rubygems -e 'require "jekyll-import"; JekyllImport::Importers::WordPress.run({ "dbname" => "<db name>", "user" => "<db user>", "password" => "<db password>", "host" => "<db host or IP>", "port" => "<db port: 3306>", "socket" => "", "table_prefix" => "wp_", "site_prefix" => "", "clean_entities" => true, "comments" => false, "categories" => true, "tags" => true, "more_excerpt" => true, "more_anchor" => true, "status" => ["publish"] })'
All imported blog ports (in HTML) are stored in
_posts
directory. See also Jekyll documentationConvert HTML files to Markdown format files (including manual works)
Frist, I converted all HTML files stored in
_posts
directory to markdown using h2m npm package# Install h2m npm package $ npm install h2m -g # Here is how to conver html to markdown using h2m # h2m test.html > test.md # Run the following one liner converted all HTML files to markdown for h in `ls -1 *.html`;do echo $h; m=$(echo $h | sed s/\.html//g).md; h2m $h > $m; ;done
Then, do some manual modification to
*.md
files. Markdown don’t support all HTML components such as embeded, iframe, align, etc. What I did for this modification parts are basically:- All embeded parts such as Youtube video, slideshare, and gist links (Markdown doesn’t support embeded tags)
- Table tags part (I used Wordpress Table plugin that express table with very special tag, which of course can not be automatically convered to Markdown )
Markdown CheatSheet was very helpful in this part
Publish the site uisng Jekyll and Github Pages
Install the same github-pages gem and ruby as the ones used in Github page
Go to this page to get ruby and github-pages version used in Github page. This time it was
- ruby: 2.4.2
- github-pages: 186
Then, I installed the exactly the same version of ruby and github-pages gem on my local
# Install Ruby using rbenv $ rbenv install 2.4.2 $ rbenv global 2.4.2 # Install github-pages ruby gem package $ gem install github-pages -v 186
Run Jekyll locally and verify the site content
Create Jekyll template site and copy all blog pages (Markdown) on to
_posts
directory under the site template root# Check jekyll version $ jekyll -v jekyll 3.7.3 # Create new Jekyll template site with jekyll command (here I create template site named `myblog`) $ jekyll new myblog $ tree myblog myblog ├── 404.html ├── Gemfile ├── _config.yml ├── _posts │ └── 2018-07-06-welcome-to-jekyll.markdown ├── about.md └── index.md # Remove Gemfile # Ruby will use the contents of your Gemfile to build your Jekyll site. So you basically add the same version of github-pages and ruby to Gemfile as the ones in Github Pages, but I removed it to make life simple as I've already synced the local version of github-pages and ruby with the ones in Github Pages but. If you possibly run Jekyll site on multiple environments, it's definitly better to manage package versions with Gemfile $ rm Gemfile # Copy all blog pages (Markdown) on to `_posts` directory under the site template root $ cp *.md _posts/
Run the local webserver like this and verify the site content:
$ jekyll s $ curl http://localhost:4000
See also Setting up your GitHub Pages site locally with Jekyll
Create Github project for hosting the site
Create my user site by following instructions in https://pages.github.com/. In this case, I’ve created yokawasa.github.io under my account https://github.com/yokawasa, by which I can access
*.html|*.md
in github.com/yokawasa/yokawasa.github.io with the URL of https://yokawasa.github.io/(*.html|*.md)
Publish the site to Github uisng git
Copy all files under Jekyll site content that I’ve verified onto yokawasa.github.io and push them to Github
$ git clone https://github.com/yokawasa/yokawasa.github.io $ cp -pr myblog/* yokawasa.github.io/ # make sure to copy .gitignore file as well $ cd yokawasa.github.io $ git add -all $ git commit -m "Initial commit" $ git push -u origin master $ open https://yokawasa.github.io
Setup Custom domain
I added my custom domain (unofficialism.info) to my Github page site by following Quick start: Setting up a custom domain. Here are what I’ve actually done:
First, check my current DNS record for my custom domain
$ dig +noall +answer unofficialism.info unofficialism.info. 146 IN A XX.XXX.XXX.XX
Then, follow my DNS provider’s instructions to create A records that point my custom domain to the following IP addresses (These are fixed IPs but these IPs can be obtained simply by running dig for username.github.com):
185.199.108.153 185.199.109.153 185.199.110.153 185.199.111.153
Confirm that the DNS record is set up correctly
$ dig +noall +answer unofficialism.info unofficialism.info. 430 IN A 185.199.108.153 unofficialism.info. 430 IN A 185.199.109.153 unofficialism.info. 430 IN A 185.199.110.153 unofficialism.info. 430 IN A 185.199.111.153
In addition, add my custom domain for my GitHub Pages site in Github Page setting page by following Adding or removing a custom domain for your GitHub Pages site
Finally, confirm the access to my Github page with my custom domain
$ curl https://unofficialism.info
-
Kubernetes x PaaS コンテナアプリケーションのNoOpsへの挑戦 (Japan Container Days v18.04)
先日、4月19日に開催されたJapan Container Days v18.04にて「Kubernetes x PaaS – コンテナアプリケーションのNoOpsへの挑戦」というタイトルでセッションを担当させていただいた。その名の通りメインがKubernetesで、KubernetesアプリケーションにおいてNoOps(運用レス)を目指すためのにどういった工夫ができるのか、どういったものを活用していけばよいのか、という内容です。このブログではJapan Container Daysでの発表に使用したスライドの共有とセッションに中のサンプルやデモについて補足させていただく。
Session Slides
Kubernetes x PaaS – コンテナアプリケーションの NoOpsへの挑戦 from Yoichi Kawasaki
補足情報
1. Open Service Broker for AzureでAzure Database for MySQLの利用
スライドでお見せした実際のファイルを使ってAzure Database for MySQLのサービスインスタンス作成、バインディング、そして実際のアプリケーションからの利用までの流れを紹介させていただく。
Open Service Broker for AzureプロジェクトのGithubにあるサンプルファイルmysql-instance.yamlとmysql-binding.yamlを使ってそれぞれServiceInstanceとServiceBindingを作成する `
# Provisioning the database, basic50 plan ... $ kubectl create -f mysql-instance.yaml # Wait until ServiceInstance named example-mysql-instance get ready 'Status => Ready', # then execute the following to create a binding for this new database, $ kubectl create -f mysql-binding.yaml
これでexample-mysql-secretという名前のシークレットオブジェクトが作成され、そこにアプリケーションがAzure Database for MySQLインスタンスとの接続必要な情報が格納される。ここではMySQLに接続して単純な処理をするだけのPythonアプリでテストする。アプリをデプロイメントのために下記YAML (
mysql-deploy.yaml
)を用意したが注目すべきはYAMLの中でMySQLの接続必要な情報をシークレットexample-mysql-secretから取得している点。apiVersion: apps/v1beta1 kind: Deployment metadata: name: sample-osba-mysql spec: replicas: 1 template: metadata: labels: app: sample-osba-mysql spec: containers: - name: osba-mysql-demo image: yoichikawasaki/sample-osba-mysql:0.0.1 ports: - containerPort: 80 env: - name: MYSQL_USER valueFrom: secretKeyRef: key: username name: example-mysql-secret - name: MYSQL_PASSWORD valueFrom: secretKeyRef: key: password name: example-mysql-secret - name: MYSQL_HOST valueFrom: secretKeyRef: key: host name: example-mysql-secret - name: MYSQL_DATABASE valueFrom: secretKeyRef: key: database name: example-mysql-secret
また、アプリケーションの中ではYAMLで指定された環境変数からMySQL接続に必要な情報を取得している。以下、サンプルアプリのコード(
sample-osba-mysql.py
)。import MySQLdb as db import os # MySQL configurations MYSQL_USER = os.environ['MYSQL_USER'] MYSQL_PASSWORD = os.environ['MYSQL_PASSWORD'] MYSQL_HOST = os.environ['MYSQL_HOST'] MYSQL_DATABASE = os.environ['MYSQL_DATABASE'] print(MYSQL_USER) print(MYSQL_PASSWORD) print(MYSQL_HOST) print(MYSQL_DATABASE) def main(): conn = db.connect( user=MYSQL_USER, passwd=MYSQL_PASSWORD, host=MYSQL_HOST, db=MYSQL_DATABASE ) c = conn.cursor() sql = 'drop table if exists test' c.execute(sql) sql = 'create table test (id int, content varchar(32))' c.execute(sql) sql = 'show tables' c.execute(sql) print('===== table list =====') print(c.fetchone()) # insert records sql = 'insert into test values (%s, %s)' c.execute(sql, (1, 'hoge')) datas = [ (2, 'foo'), (3, 'bar') ] c.executemany(sql, datas) # select records sql = 'select * from test' c.execute(sql) print('===== Records =====') for row in c.fetchall(): print('Id:', row[0], 'Content:', row[1]) conn.commit() c.close() conn.close() if __name__ == '__main__': main()
それでは次のようにアプリケーションをデプロイする
$ kubectl create -f mysql-deploy.yaml
全ての過程が問題なければ、デプロイ後のPodのログをみると、下記のような出力が確認できるはずだ。これはアプリケーションがMySQLとの接続して処理が行われたことを表す。ここではsternを使ってログを参照している。
$ stern <アプリケーションのPod名> + sample-osba-mysql-684ccd679f-nl252 › osba-mysql-demo sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo o36e6ivtni@8ae3fca5-9b5c-471b-99d8-0eeb567c6acb sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo sE8UFm5cN4tgIeNF sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo 8ae3fca5-9b5c-471b-99d8-0eeb567c6acb.mysql.database.azure.com sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo v8i0xxlerz sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo ===== table list ===== sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo ('test',) sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo ===== Records ===== sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo Id: 1 Content: hoge sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo Id: 2 Content: foo sample-osba-mysql-684ccd679f-nl252 osba-mysql-demo Id: 3 Content: bar
2. デモ - Virtual Kubelet + Azure Container Instances
- Demo Video: Image Processing with Virtual Kubelet + ACI Demo
- Demo Code: https://github.com/rbitia/aci-demos
3. デモ - Traffic Routing with Istio
- Demo Video: Traffic Routing with Istio Demo
セッション中に時間が足りなくてチラ見せ程度しかお見せできなかったサービスメッシュにIstio(Istio-0.5.0)を使ったトラフィックルーティングデモ。せっかくなのでここで全ての手順を紹介させていただく。アプリな単純なコンテナイメージのタグ名を表示するだけのFlaskアプリを利用している
必要ファイル一覧
- myversion-v1.yaml
- myversion-v2.yaml
- route-default-v1.yaml
- route-canary.yaml
- route-conditional-v2.yaml
まずはV1とV2アプリケーションのデプロイメント。ここではアプリケーションのManifestに対してistioctlのkube-injectでIstioの設定が組み込まれたManifestを元にデプロイメントしている。
## ver1.0 $ kubectl apply -f <(istioctl kube-inject --debug -f myversion-v1.yaml) ## ver2.0 $ kubectl apply -f <(istioctl kube-inject --debug -f myversion-v2.yaml)
上記のデプロイメントで作られたIngressコントローラーのIP、PORTを取得を次のように取得する。サンプルで使用しているFlaskアプリで指定しているエンドポイントが/versionであるからアプリケーションのエンドポイントはGATEWAY_IP:GATEWAY_PORT/versionがとなる。
GATEWAY_IP=$(kubectl get po -n istio-system -l \ istio=ingress -n istio-system \ -o 'jsonpath={.items[0].status.hostIP}') GATEWAY_PORT=$(kubectl get svc istio-ingress \ -n istio-system -n istio-system \ -o 'jsonpath={.spec.ports[0].nodePort}') GATEWAY_URL=$GATEWAY_IP:$GATEWAY_PORT echo $GATEWAY_URL
まずは、Istioに全てのトラフィックをv1アプリにルーティングするように設定する
$ istioctl create -f route-default-v1.yaml
次のように連続でアクセスして全てのトラフィックがV1にルーティングされていることを確認
$ while true; do curl http://${GATEWAY_URL}/version; sleep 1; done I am v1.111111111 I am v1.111111111 I am v1.111111111 I am v1.111111111
続いて、Istioにさきほどの100% V1の設定を削除して、新しく90%のトラフィックをv1アプリに 10%をV2アプリにルーティングするように設定する
$ istioctl delete routerule myversion-default-v1 -n default $ istioctl create -f route-canary.yaml
前と同様に連続でアクセスして90%のトラフィックはV1に、10%はV2にルーティングされていることを確認
$ while true; do curl http://${GATEWAY_URL}/version; sleep 1; done I am v1.111111111 I am v1.111111111 I am v1.111111111 I am v2.222222222 ... たまにV2 I am v1.111111111
最後に、Istioに特定の条件でのみ100%のトラフィックをV2アプリ向けるように設定する。下記設定ファイル
route-conditional-v2.yaml
に記述されているように、ここではHTTPヘッダのuserの値が”yoichi”であることを特定の条件とする。--- apiVersion: config.istio.io/v1alpha2 kind: RouteRule metadata: name: myversion-conditional-v2 spec: destination: name: myversion precedence: 2 match: request: headers: user: regex: "yoichi" route: - labels: version: v2.0
Istioに特定条件用のルーティング設定を追加
$ istioctl create -f route-conditional-v2.yaml
次のようにヘッダーに”user: yoichi”の条件を追加して連続でアクセスして全てのトラフィックがV2にルーティングされていることを確認
$ while true; do curl -H "user: yoichi" http://${GATEWAY_URL}/version; sleep 1; done I am v2.222222222 I am v2.222222222 I am v2.222222222 I am v2.222222222
以上、補足情報でした。
Links
-
Controlling Azure Media Services traffic with Traffic Manager
This is an article on how you can achieve Azure Media Services (AMS) streaming traffic distribution with Traffic Manager.
The process for a client to find target AMS streaming endpoints
The figure shows how a client find target AMS streaming endpoints with Traffic Manager and requests from video players are distributed to streaming endpoints in AMS:
When AMS endpoints are added to an Azure Traffic Manager profile, Azure Traffic Manager keeps track of the status of the endpoints (running, stopped, or deleted) so that it can decide which of those endpoints should receive traffic. You can configure the way to route network traffic to the endpoints by choosing traffic routing methods available in Traffic Manager.
Configuration procedure
Suppose that you have 2 AMS accounts (amsaccount1, amsaccount2), and that you want to distribute requests to your Traffic Manager domain (myamsstreaming.trafficmanager.net) from video player clients to streaming endpoints in AMS. When AMS endpoints are added to an Azure Traffic Manager profile (myamsstreaming), Azure Traffic Manager keeps track of the status of your AMS streaming endpoints (running, stopped, or deleted) so that it can decide which of those endpoints should receive traffic. However, when it comes to AMS endpoints, it has to be toward a custom domain, NOT simply a Traffic Manager domain for clients’ traffic to be distributed into AMS endpoints using Traffic Manager. So let’s suppose you prepare a custom domain: streaming.mydomain.com.
Example accounts and domains
- AMS Account1: amsaccount1 (Streaming endpoint: amsaccount1.streaming.mediaservices.windows.net)
- AMS Account2: amsaccount2 (Streaming endpoint: amsaccount2.streaming.mediaservices.windows.net)
- Traffic Manager Domain: myamsstreaming.trafficmanager.net
- Custom Domain: streaming.mydomain.com
(1) Point a custom domain to a Traffic Manager domain
You add the following alias (CNAME) to point the custom domain to the traffic manager domain:
streaming.mydomain.com IN CNAME myamsstreaming.trafficmanager.net
Useful Link for this step: Point a company Internet domain to an Azure Traffic Manager domain
(2) Add Azure Media Services origin hosts to the Traffic Manager
Add AMS endpoints to an Azure Traffic Manager profile as “External Endpoint” via either Azure Portal or Azure CLI / PowerShell. Here is an image of adding endpoints in Azure portal:
Useful Link for this step: Add, disable, enable, or delete endpoints
(3) Custom domain name ownership verification
First of all, get Media Service Account IDs (GUID) for your AMS accounts in this step. To find the Azure Media Service ID , go to the Azure portal and select your Media Service account. The Azure Media Service ID appears on the right of the DASHBOARD page. Let’s suppose you get the following account IDs for AMS accounts (amsaccount1, amsaccount2):
- Account ID: 8dcbe520-59c7-4591-8d98-1e765b7f3729 for AMS account: amsaccount1
- Account ID: 5e0e6784-4ed0-40a0-8444-33da6d4f7171 for AMS account: amsaccount2
Then, create CNAME that maps (accountId).(parent custom domain) to verifydns.(mediaservices-dns-zone). This is necessary to proves that the Azure Media Services ID has the ownership of the custom domain. Here are CNAMEs to create in this step:
## <MediaServicesAccountID>.<custom parent domain> IN CNAME verifydns.<mediaservices-dns-zone> ## Custom name Ownership verification for amsaccount1 8dcbe520-59c7-4591-8d98-1e765b7f3729.mydomain.com IN CNAME verifydns.mediaservices.windows.net ## Custom name Ownership verification for amsaccount2 5e0e6784-4ed0-40a0-8444-33da6d4f7171.mydomain.com IN CNAME verifydns.mediaservices.windows.net
Refer to CustomHostNames section of StreamingEndpoint document to learn more about the configuration in this step.
(4) Add Custom host name to each Azure Media Service streaming endpoint
Once you completed “Custom domain name ownership verification” configuration, you then need to configure to add custom host name to each Azure Media Service streaming endpoint. Unfortunately new portal doesn’t include capability to add custom domain to the streaming endpoint. You can set it either using REST API directly or using Azure Media Explorer. Here is how you add custom host name to the streaming endpoint in Azure Media Explorer:
Choose “Streaming endpoint” in the top menu, right click on your streaming endpoint, and select “Streaming endpoint information and settings”. In Streaming endpoint information form, type in your custom host name for the endpoint, and click “Update settings and close”. That’s it.
(5) Test video playback with your custom domain
Once all configurations above are completed (+ DNS settings are reflected), you will see the custom domain name lookup points to either of AMS endpoints added to the traffic manager like this:
$ dig streaming.mydomain.com ;; ANSWER SECTION: streaming.mydomain.com. 600 IN CNAME myamsstreaming.trafficmanager.net. myamsstreaming.trafficmanager.net. 300 IN CNAME amsaccount1.streaming.mediaservices.windows.net. amsaccount1.streaming.mediaservices.windows.net. 60 IN CNAME wamsorigin-origin-903f1f37105244fba2270ae7b64021bd.cloudapp.net. wamsorigin-origin-903f1f37105244fba2270ae7b64021bd.cloudapp.net. 60 IN A 104.215.4.76
Make sure to check if the custom name lookup points to the other endpoint when one of the endpoints are down.
Finally, check if you can playback video with your custom domain.
$ curl http://amsaccount1.streaming.mediaservices.windows.net/ee2e5286-d3fa-40fc-a393-c3c2a3ca5a84/BigBuckBunny.ism/manifest <?xml version="1.0" encoding="UTF-8"?><SmoothStreamingMedia MajorVersion="2" MinorVersion="2" Duration="84693333" TimeScale="10000000"><StreamIndex Chunks="2" Type="audio" Url="QualityLevels({bitrate})/Fragments(aac_eng_2_128={start time})" QualityLevels="1" Language="eng" Name="aac_eng_2_128"><QualityLevel AudioTag="255" Index="0" BitsPerSample="16" Bitrate="128000" FourCC="AACL" CodecPrivateData="1190" Channels="2" PacketSize="4" SamplingRate="48000" /><c t="0" d="60160000" /><c d="24533333" /></StreamIndex><StreamIndex Chunks="2" Type="video" Url="QualityLevels({bitrate})/Fragments(video={start time})" QualityLevels="5"><QualityLevel Index="0" Bitrate="2896000" FourCC="H264" MaxWidth="1280" MaxHeight="720" CodecPrivateData="000000016764001FACD9405005BB011000000300100000030300F18319600000000168EBECB22C" /><QualityLevel Index="1" Bitrate="1789000" FourCC="H264" MaxWidth="960" MaxHeight="540" CodecPrivateData="000000016764001FACD940F0117EF011000003000100000300300F1831960000000168EBECB22C" /><QualityLevel Index="2" Bitrate="946000" FourCC="H264" MaxWidth="640" MaxHeight="360" CodecPrivateData="000000016764001EACD940A02FF97011000003000100000300300F162D960000000168EBECB22C" /><QualityLevel Index="3" Bitrate="612000" FourCC="H264" MaxWidth="480" MaxHeight="270" CodecPrivateData="0000000167640015ACD941E08FEB011000000300100000030300F162D9600000000168EBECB22C" /><QualityLevel Index="4" Bitrate="324000" FourCC="H264" MaxWidth="320" MaxHeight="180" CodecPrivateData="000000016764000DACD941419F9F011000000300100000030300F14299600000000168EBECB22C" /><c t="0" d="60000000" /><c d="24583333" /></StreamIndex></SmoothStreamingMedia>
$ curl http://streaming.mydomain.com/ee2e5286-d3fa-40fc-a393-c3c2a3ca5a84/BigBuckBunny.ism/manifest <?xml version="1.0" encoding="UTF-8"?><SmoothStreamingMedia MajorVersion="2" MinorVersion="2" Duration="84693333" TimeScale="10000000"><StreamIndex Chunks="2" Type="audio" Url="QualityLevels({bitrate})/Fragments(aac_eng_2_128={start time})" QualityLevels="1" Language="eng" Name="aac_eng_2_128"><QualityLevel AudioTag="255" Index="0" BitsPerSample="16" Bitrate="128000" FourCC="AACL" CodecPrivateData="1190" Channels="2" PacketSize="4" SamplingRate="48000" /><c t="0" d="60160000" /><c d="24533333" /></StreamIndex><StreamIndex Chunks="2" Type="video" Url="QualityLevels({bitrate})/Fragments(video={start time})" QualityLevels="5"><QualityLevel Index="0" Bitrate="2896000" FourCC="H264" MaxWidth="1280" MaxHeight="720" CodecPrivateData="000000016764001FACD9405005BB011000000300100000030300F18319600000000168EBECB22C" /><QualityLevel Index="1" Bitrate="1789000" FourCC="H264" MaxWidth="960" MaxHeight="540" CodecPrivateData="000000016764001FACD940F0117EF011000003000100000300300F1831960000000168EBECB22C" /><QualityLevel Index="2" Bitrate="946000" FourCC="H264" MaxWidth="640" MaxHeight="360" CodecPrivateData="000000016764001EACD940A02FF97011000003000100000300300F162D960000000168EBECB22C" /><QualityLevel Index="3" Bitrate="612000" FourCC="H264" MaxWidth="480" MaxHeight="270" CodecPrivateData="0000000167640015ACD941E08FEB011000000300100000030300F162D9600000000168EBECB22C" /><QualityLevel Index="4" Bitrate="324000" FourCC="H264" MaxWidth="320" MaxHeight="180" CodecPrivateData="000000016764000DACD941419F9F011000000300100000030300F14299600000000168EBECB22C" /><c t="0" d="60000000" /><c d="24583333" /></StreamIndex></SmoothStreamingMedia>
Useful Links
-
15分でお届けするElastic Stack on Azure設計・構築ノウハウ
UPDATED on Feb 3, 2018 - Elastic社イベントサイトを追加
イベント開催日から少々時間が経過したが、Elastic {ON} Tour 2017 東京(2017年12月14日開催)というElastic社オフィシャルのユーザーカンファレンスにて登壇させていただく機会があり、そこで「15分でお届けする Elastic Stack on Azure 設計・構築ノウハウ」というお題でお話をさせていただいた。個人的にとても大好きなプロダクトなので、そのユーザーカンファレンスでお話をさせていただいたということと、そのプロダクトのAzureでの利用促進に微力ながらも貢献できたということは光栄至極である。ここではそのElastic {ON} Tourでの発表で使用したスライドに補足解説を加えて共有させていただく。
セッションスライド(+デモ動画)
15分でお届けする Elastic Stack on Azure 設計・構築ノウハウ from Yoichi Kawasaki
補足解説
デプロイメント
AzureでのElastic Stackの利用は当然ながら仮想マシン(VM)を並べてそこにクラスタを構築することになる。残念ながら現時点でマネージドのElasticサービスはAzureには存在しない。VMベースということで特にオンプレと変わらずマニュアルであったり、ChefやAnsibleなどの構成管理ツールを使ってクラスタを組んだり柔軟な構築が可能であるものの、ここではAzureでの構築ということでARMテンプレートを使ったデプロイメントの方法を紹介している。
- Azure Marketplaceからのデプロイ:最も手っ取り早い方法。30日のX-Packトライアルライセンスが付いていて、トライアル期間が過ぎてもBYOLでライセンスの更新が可能。テンプレートでは2017年12月時点でv2.0.2 〜 v5.6.3の選択が可能。何も考えず最新版をご利用ください。
- Github上のARMテンプレートをカスタマイズしてデプロイ:Elastic社が用意したGithub上のARMテンプレートがあるのでそれを自分の要件に応じてカスタマイズしてデプロイメントをする。Azure CLIやPowerShellなどコマンドを使ったデプロイメントが可能なので構成管理ツールに組み込んで周辺環境を合わせて自動構築設定も可能。慣れてきたらこちらがよいでしょう。
推奨仮想ハードウェアとDISK
Elasticクラスタ全体のパフォーマンスを引き出すためには機能別に適正なVMインスタンスとサイズを選択ください。またVMにアタッチするディスクについてはビルトインで可用性設定がされているManaged Disk、もしくはPremium Managed Diskを選択することをお忘れなく。
可用性の設定について
AzureでIaaSで可用性の設定といえばおなじみの可用性セット(Availability Set)と可用性ゾーン(Availability Zone)。当然Elastic Stackのクラスタを組む時もこれらの設定を入れましょうというお話。可用性ゾーンは、その可用性レベルの高さから将来的には可用性ゾーンが主流な設定になっていくはずであるものの、2017年12月時点でPreviewリリースであり、利用可能リージョンが米国東部第2、西ヨーロッパのみというとても限定的なものとなっている。現時点でプロダクション用途となると可用性セット一択なので何も考えずに可用性セットを組んでください。
可用性セット(Availability Set)
- 一つのDCの中で同一の物理ラックや電源などを配置しないようにして、障害が発生してもグループの中のどこかのVMは生きているようにする設定のこと
- VM SLA 99.95%で提供
可用性ゾーン(Availability Zone)
- 各VMを別々のゾーンに配置するのでDCレベルの障害につよい(それぞれゾーンは電源、ネットワーク、冷却装置が完全に物理的に分離されたものとなっている)。ちなみに、Azureのリージョンは複数のデータセンターで構成されており、その間を高速なバックボーンで接続して1つのリージョンとして透過的に利用が可能となっているのでこのようなことができるわけだ
- VM SLA 99.99%で提供
- 【注意点】可用性ゾーンの設定ではDCが分かれて配置されるので次の2点の考慮が必要:(1)マスターは各ゾーンに分散するように各ゾーン最低1ノード配置すること(2)データノードはゾーンにまたがる通信が極力起こらないように工夫すること。これを実現するのがShard Allocation Awarenessという仕組みで、この仕組みをつかうことで 同一ゾーン内に配置されているノードだけで完全なシャードを保持するようにして、検索要求が同一ゾーン内で完結できるように設定が可能となる
ネットワークセキュリティグループの設定
AzureのIaaSにおけるネットワークフィルタリングの設定に、ネットワークセキュリティグループ(NSG)とよばれるL4フィルタリングがある。当然ながら、既にX-Packを導入していればそのセキュリティ機能の1つとしてネットワークレベルのアクセス制御についても行うことができるが、X-Packを導入していない場合は確実にNSGの設定は必要になってくる。また、Elastic Stack以外のアプリケーションとの連携の際にも必ず必要になってくる。Azure上でのシステム構築では欠かすことのできない設定の1つ。
Azureサービスからのデータコレクション
Azure VMについては、オンプレ同様に、ビルトインのBeatsやlogstashとの連携により、そのログやMetricsなどのデータコレクションを実現することができる。一方、Azureが特に力を入れているPaaS(Platform as a Services)からのデータコレクションについてはどうかというと、下記のサービスについては既にビルトインで用意されている機能や、コミュニティ製Logstash Input プラグインを利用することでデータコレクションを実現することができる。 H2M_LI_HEADER Azure Blob Storage: logstash-input-azureblob H2M_LI_HEADER Azure Service Bus (Topic): logstash-input-azuretopic H2M_LI_HEADER Azure Event Hub: logstash-input-azureeventhub H2M_LI_HEADER Azure SQL Database: logstash-input-jdbc H2M_LI_HEADER Azure Database for MySQL: logstash-input-jdbc H2M_LI_HEADER Azure Database for PostgreSQL: logstash-input-jdbc H2M_LI_HEADER Azure HDInsight: ES-Hadoopによる連携
ちなみに、Azureサービス向けLogstashプラグイン一覧についてはこちら - Logstash plugins for Microsoft Azure Services
Azure Diagnostics、Activities、Metricsログのコレクション
基本的にIaaS、PaaS問わずAzureのほとんどのサービスから下記の情報が出力され、これらの情報はBlobストレージまたはEvent Hubに出力設定が可能となっている。 H2M_LI_HEADER 診断ログ(Diagnostics log) H2M_LI_HEADER アクティビティログ(Activity log) H2M_LI_HEADER メトリック
また上記に加えて、PaaSサービスに展開するアプリケーション固有のログについても少なくともBlobストレージに書き込むことはできる。つまるところ、上記データコレクションの項目でご紹介したようにBlobストレージやEvent hubに出力されたデータはLogstashを通じてElastic Stackに取り込むことが可能であり、Azureリソース関連情報を含めた全てのログはElastic Stackで一元管理することができるのである。
参考Links
- Deploying Elasticsearch on Microsoft Azure
- Microsoft AzureにElasticsearchをデプロイする
- Elasticsearch and Kibana Deployments on Azure
- Spinning up a cluster with Elastic’s Azure Marketplace template
- Run Elasticsearch on Azure
- Public preview: Azure Availability Zones
- Filter network traffic with network security groups
- Shared Allocation Awareness
- Azure Diagnostics Tools
Elastic{ON} Tour Tokyo 2017イベントLinks
-
Azure Functions Python Programming - Experimental
今年もあと少し。ほぼ趣味の範囲を超えないレベルで今年取り組んだテーマの1つにAzure Functions with Pythonがある。あまり情報が無い中、興味本位でサンプルコードを作っては動かして試して得られた情報をシコシコとGithubに上げているうちにナレッジが溜まって来た。それほど多くはないと思うがPythonでAzure Functionsアプリを作りたいという人もいると思うのでノウハウをブログにまとめておく。いきなり水を差すようではあるが、現時点(2017年12月)ではAzure FunctionsのPythonサポータビリティはExperimental(実験的サポート)でありプロダクション向きではない状況であるので、ホントにPythonが好きな人がOn your own riskで楽しんでいただければと思う。
Azure FunctionsのPythonサポート状況
Azure FunctionsのRuntimeには大きく1系と2系の2種類あるが、現時点でPythonは1系でのみExperimentalサポートという状況( See also 言語サポート状況)
Experimental(実験的サポート)なので本番での利用は非推奨であり、公式サポートはない(ベストエフォートでのサポートは得られるはず)。また、当然ながらGA言語に比べパフォーマンスは悪い。PythonはFunction呼び出し毎にpython.exeが実行される(GA言語はRuntimeと同じプロセスで実行)。
将来的な話をすると、Azure Functions Runtime 1系でのPythonサポートについては今のExperimentalの域を超えることはないだろう。一方、Runtime 2系ではPythonが正式サポートされるように対応が進められている。ただし時期は未定。この対応については下記Github Issueが切られており、ある程度の対応状況であれば確認可能。Pythonを使う利点の1つに、強力な数理計算、自然言語解析、機械学習系モジュールがあるが、早く安定とパフォーマンスが備わったPythonサーバレスアプリ実行環境でこれら強力なモジュールを活用できたらと思うのは私だけではないだろう。今後の進展に期待。
Hosting Planの選択について
Consumption Plan vs App Service Plan
Azure FunctionsのHosting PlanにはConsumption PlanとApp Service Planの2つがあって、言語に関係なく各プランの特徴は次の通り:
Consumption Plan
- コード実行時にコンピューティング割り当て
- リソース使用量(関数実行時間、使用メモリ)で課金
- 自動スケール、各処理は〜10分まで
App Service Plan
- 専用VMでリソース確保
- 継続処理:10分以上の処理
- App Service環境でのみ可能な処理: App Service Environment, VNET/VPN接続, より大きなサイズのVM, etc
Pythonで使う上で気をつけるポイント
- Python 3.XなどRuntimeの変更を行う場合は、専用環境である必要があってApp Service Plan必須
- Consumption Planの場合、Pythonに限らずColdスタート問題という休眠したFunctionの起動が極端に遅くなる問題があるのだが、Pythonの場合は、GA言語に比べてパフォーマンスが悪く、SciPyなど重めのモジュールを利用すると絶望的に遅くなることからConsumption Planでの問題が特に顕著にでてくる。これまでの経験から、小さいインスタンスを並べるConsumption Planよりも比較的大きなサイズのVMが選べるApp Service Planの方が向いていることが多い。Pythonの場合は、予測可能なワークロードに対してApp Service Planで使うほうが問題が少ない。Consumption Planの魅力であるMicro Billing(使った分だけ課金)やリクエストに応じたオートスケーリングといった真のサーバレスに期待される要件は既に正式サポートしているC#、Nodeでやっていただくのがよいかと。
[参考] Coldスタート問題
- Consumption Planにおける問題
- Azure Functions Cold Start Workaround
- The only downside is that the consumption model that keeps the cost so dirt-cheap means that unless you are using your Function constantly (in which case, you might be better off with the non-consumption options anyway), you will often be hit with a long delay as your Function wakes up from hibernation
- 休眠したFunctionをどう起こすかがポイント。事前に空リクエストを送ることが考えられるが問題はタイミング(フォーム開いた時とか)
Python 3.Xランタイムへの変更方法
2017年12月時点のAzure FunctionsのデフォルトPython Runtimeは2.7.8である。Site ExtensionにPython3.5系とPython3.6系が用意されているので、それを利用してFunctionsで利用するPython Runtimeを変更する方法を下記ページに纏めた。
モジュールのインストール方法
pipとKudu DebugConsole/UIを利用した2種類のモジュールインストール方法を下記ページに纏めた。
Pythonサンプルコード
私が試したTriggerとBinding利用サンプルコードは全て下記Githubプロジェクトに追加するようにしている。もしこれを読んでいる皆さんで下記プロジェクトでカバーされていないTrigger/Bindingの組み合わせを試されたら是非ともコントリビュートください。
スライドとHands-onマテリアル
Azure Antennaにて2017年11月20日と11月28日に実施したセッション資料:
PythonによるAzureサーバレスアプリケーション開発 / Serverless Application Development with Python from Yoichi Kawasaki
Hands-onマテリアル:
それでは、Enjoy Serverless Application Development with Python!
[追記] 上記セッションに関する記事
-
Developing Full Managed Search Application in Azure
これは9/29 Azure Web Seminar 「Azure サービスを活用して作るフルマネージドな全文検索アプリケーション」のフォローアップ記事です。なかなか暇ができず少々時間が経過してしまいました。
Azure サービスを活用して作るフルマネージドな全文検索アプリケーション from Yoichi Kawasaki
Sample Application & Source Code
セミナーで紹介したサンプルアプリはAzure公式サイトに載せてある代表的なサービスのFAQデータを元にしたHTML/CSS/JavascriptによるQ&Aナレジッジベース検索のシングルページアプリケーションです。検索エンジンにAzure Searchを使い、データソースにCosmos DBを使いAzure SearchのCosmosDB Indexerでクローリングする構成にしてます。ソースコードと設定手順は以下Githubプロジェクトにアップしてあります。もしバグや設定手順等でご質問があればGithubでIssue登録いただければ時間を見つけて対応させていただきます。
Source Code: https://github.com/yokawasa/azure-search-qna-demo/
Demo: AI Digital Media Search
セミナー中に紹介した非構造化データの全文検索デモとして紹介したAI Digital Media Searchアプリケーション。メディア x 音声認識 x 機械翻訳 x 全文検索全てを絡めた面白いアプリケーションなのでこちらでデモ動画とソースコードを共有します。またこのアプリはAzure PaaSサービスを組み合わせてプレゼンテーションレイヤー(Web App for Container)のみならずデータ生成部分(AMS, Functions, Logic App)も全てサーバレスで実現しているのでこのエリアのサンプルアプリとしてもとても良いものになっていると思います。
- Demo Video: AI Digital Media Search Demo
- Source Code: https://github.com/shigeyf/ai-digitalmedia
AzureSearch.js - Azure Search UIライブラリ
AzureSearch.jsはAzure SearchのUIライブラリで、Azure Searchプロダクトチーム主要開発者により開始されたOSSライブラリです。TypeScriptで書かれているのでとても読みやすく、また、ライブラリが提供するオブジェクト操作により非常に短いコードでサーチボックス、結果出力、ページネーション、ファセット、サジェスションなどで構成されるサーチ用UIを簡単に組み立てることが可能です。なかなかいけているライブラリにもかかわらず、あまり世の中に知られていないのはもったいないと思いセミナーの最後で紹介させていただきました。これ使わない手はないです。手っ取り早くは、下記のAzureSearch.jsアプリテンプレートジェネレータページで皆さんのAzure SearchアカウントのQueryKeyとインデックススキーマ(JSONフォーマット)を入力するとAzureSearch.jsアプリの雛形が生成されますので、そこから始めるのがよいかと思います。
END
-
Azure Search Text Analyzer Tools - azure-search-ta
Azure Searchのアナライザーによるテキスト解析結果を出力する(だけの)ツールを作ってみたのでここで紹介します。その名もazure-search-ta(ta=Test Analyzer)。中身はAzure SearchのAnalyzer APIの出力結果を整形して表示させていているだけの単純なものでありますが、Azure Searchの全文検索チューニングやキーワードにヒットしない原因調査をする際には役に立つと思ってます。「どうしてこのキーワードがひっかからないの?」を突き詰めるには最終的にアナライザのテキスト解析結果と突き合わせる必要があるのと、アナライザーを選択する際にテキスト解析が視覚化されていると判断しやすいだろうと。ツールは2種類で (1)Web UIツールと(2)コマンドラインツール
Web UI Tool
https://github.com/yokawasa/azure-search-ta
インストールは超簡単。(1)Githubからazure-search-taをclone (2)azure-search-ta/ui 配下のファイルをPHPが動くWebサーバにコピー (3)analyze-api.phpをエディタで開いてお使いのAzure Searchカウント名とAzure Search API Adminキーの値を設定ください。あとはazure-search-ta-ui.htmlにアクセスいただければ上記のようなUIが出力されるはずです。なぜHTML/JSだけではなく間にPHPを挟んでいるのかについて、Azure SearchのAnalyze APIや管理系APIリクエストに位置付けられており、管理系APIはvia CORSでのリクエストを受け付けていないからである。
$ git clone https://github.com/yokawasa/azure-search-ta.git` $ vi azure-search-ta/ui/analyze-api.php $azureSearchAccount=""; $azureSearchApiKey = "";
Command-Line Tool
1. インストールと設定
pipでazure-search-taパッケージをインストール。既に古いバージョンをインストール済みでアップデートする際は――upgradeをつけて実行ください。
$ pip install --user azure-search-ta
次に、search.confにお使いのAzure Searchカウント名とAzure Search API Adminキーの値を設定ください。
# Azure Search Service Name ( never put space before and after = ) SEARCH_SERVICE_NAME= # Azure Search API Admin Key ( never put space before and after = ) SEARCH_API_KEY=
2. 使い方
いくつか使い方を紹介します。
usage: azure-search-ta [-h] [-v] [-c CONF] [-i INDEX] [-a ANALYZER] [-t TEXT] [-o OUTPUT]` This program do text analysis and generate formatted output by using Azure Search Analyze API optional arguments: -h, --help show this help message and exit -v, --version show program's version number and exit -c CONF, --conf CONF Azure Search Configuration file. Default:search.conf -i INDEX, --index INDEX Azure Search index name -a ANALYZER, --analyzer ANALYZER Azure Search analyzer name -t TEXT, --text TEXT A file path or HTTP(s) URL from which the command line reads the text to analyze -o OUTPUT, --output OUTPUT Output format ("simple" or "normal"). Default:normal
ja.microsoftアナライザーによるテキスト解析結果をnormalモードで出力する例。Analyzer APIはパラメータにインデックス名が必要なので、なんでもいいのでご自分のアカウントに設定されているインデックス名を指定ください。ここではインデックスtaでsimple.txtに対象のテキストを記入して実行しています。
$ cat sample1.txt 吾輩は猫である $ azure-search-ta -c ./search.conf -i ta -a ja.microsoft --t sample1.txt INPUT: 吾輩は猫である TOKENS: [吾輩] [猫] [ある]
Azure Searchにビルトインされているアナライザーでけでなく皆さんが作成したカスタムアナライザーによるテキスト解析結果も当然出力可能です。以下は、インデックスtacustomにNグラム分割のカスタムアナライザーmy_ngramを作成したとしてmy_ngramアナライザーによるテキスト解析結果を出力する例です。カスタムアナライザーの定義はGithubページのほうに詳しく書いているのでよかったらどうぞ。
$ cat sample1.txt 吾輩は猫である $ azure-search-ta -c ./search.conf -i tacustom -a my_ngram --t sample1.txt -o simple '吾輩' '吾輩は' '吾輩は猫で' '吾輩は猫' '輩は猫であ' '輩は' '輩は猫' '輩は猫で' 'は猫であ' 'は猫で' 'は猫' 'は猫である' '猫であ' '猫で' '猫で ある' 'である' 'であ' 'ある'
他には、azure-search-taはインターネット上のページのテキスト解析機能も付いているので、そいつを試してみます。ja.luceneアナライザを使ってhttp://www.yahoo.co.jpトップページの内容を解析します。
$ azure-search-ta -c ./search.conf -i ta -a ja.lucene --t http://www.yahoo.co.jp -o simple 'html' 'public' 'w' '3' 'c' 'dtd' 'html' '4' '01' 'transitional' 'en' 'http' 'www' 'w' '3' 'org' 'tr' 'html' '4' 'loose' 'dtd' 'yahoo' 'japan' 'ヘルプ' 'yahoo' 'japan' 'トップページ' '機能' '正しく' 'ご' '利用' 'いただく' '下記' '環境' '必要' 'windows' 'internet' 'explorer' '9' '0' '以上' 'chrome' '最新' '版' 'firefox' '最新' '版' 'microsoft' 'edge' 'macintosh' 'safari' '5' '0' '以上' 'internet' 'explorer' '9' '0' '以上' 'ご' '利用' '場合' 'internet' 'explorer' '互換' '表示' '参考' '互換' '表示' '無効' '化' '試し' 'くださる' '東北' '自転車' 'イベント' '参加' '方法' '事前' 'チェック' 'こだわり' 'ご' '当地' 'スイーツ' '取り寄せる' '上海' 'マージャン' '定番' 'ゲーム' '無料' '遊ぶ' 'ニュース' '11' '時' '1' '分' '更新' '韓国' '北' '太陽' '政策' '回帰' '娘' '放置' '熱中' '症' '死なす' '逮捕' '保育' '死亡' '事故' '睡眠' '中' '注意' '三菱' 'ufj' '法人' '融資' '銀行' '集約' 'フレーバ' '水' '人気' '続く' '各国' '大' '規模' 'サイバ' '攻撃' '西武' '菊池' '沢村' '超' '驚異' '被' '打率' '寺島' 'しのぶ' '長男' '超' '英才' '教育' 'もっと' '見る' '記事' '一覧' 'ゴミ' '収集' '車' '子育て' '5' '月' '13' '日' '7' '時' '55' '分' '配信' '産経新聞' 'ショッピング' 'ヤフオク' '旅行' 'ホテル' '予約' 'ニュース' '天気' 'スポーツナビ' 'ファイナンス' 'テレビ' 'gyao' 'y' 'モバゲ' '地域' '地図' '路線' '食べる' 'ログ' '求人' 'アルバイト' '不動産' '自動車' '掲示板' 'ブログ' 'ビューティ' '出会い' '電子' '書籍' '映画' 'ゲーム' '占い' 'サービス' '一覧' 'ログイン' 'id' 'もっと' '便利' '新規' '取得' 'メール' 'メールアドレス' '取得' 'カレンダ' 'カレンダ' '活用' 'ポイント' '確認' 'ログイン' '履歴' '確認' '会社' '概要' '投資' '家' '情報' '社会' '的' '責任' '企業' '行動' '憲章' '広告' '掲載' '採用' '情報' '利用' '規約' '免責' '事項' 'メディア' 'ステートメント' 'セキュリティ' '考え方' 'プライバシ' 'ポリシ' 'copyright' 'c' '2017' 'yahoo' 'japan' 'corporation' 'all' 'rights' 'reserved'
もう少しだけGithubのほうには詳しく書いてあるのでそちらも参考にしてください。
-
Python Easter Egg
Python Easter Egg = Pythonの隠しクレジットとはいってもPython基礎本などでよく紹介されているものなので既にご存知かもしれないが背景が面白いのでここで紹介。
Pythonにはthisモジュールという「The Zen of Python」(Note 1)を出力するだけのモジュールがある。このモジュール、中身(Note 2)を見てみると分かるが、総ステップにしてわずか28行、ROT13暗号化(Note 3)された文字列を復号化するだけの単純で取るに足らないものかもしれないがこのモジュールが作られた背景は面白い。Barry Warsaw氏が記事「import this and The Zen of Python」でthisモジュールが誕生にまつわる面白い話を紹介している。
「import this and The Zen of Python」の一部簡訳
2001年秋、Foretec Seminar社はのInternational Python Conference #10(以下IPC10、Pyconの前身となるカンファレンス)の準備をしておりPythonコミュニティからそのカンファレンスのスローガンを求めていた。スローガンはTシャツにもプリントされる予定だった。Guideや、Fred、Jeremyや著者達はかつてはForetec Seminar社に所属していたがPythonlabsを結成する2000年に同社を去っている。そしてPythonlabsはPythonコミュニティからのスローガン応募の審査と勝者の選定を担当することになった。応募は500くらいあったが、どれもひどいものだった。Timと著者は1つに絞られるまで何度となく選別作業を行い
最終的に”import this”を選んだ。理由は”import this”という言葉の持つふざけた、小バカにしたようなトーンが好きだったからという。
著者たちはこの”import this”をスローガンに選んですぐにthisモジュール(this.py)を実装した。モジュールは「The Zen of Python」を出力するだけのものだったが途中TimやGuidoの提案でrot13で暗号化して内容を少し難読化する工夫がされたりもした。IPC10が終わってすぐ、彼らはこのイベントを記念してthisモジュールをPython2.2.1ブランチにコミットした。この時、著者の提案で他の誰にも知られないようにするためにソース管理システムのチェックイン通知機能を停止し、こっそりこのモジュールをPython2.2.1のブランチに含めたのだ。これらのことは彼ら以外に誰にも知らせず内緒で行われた。著者いわく、この彼らの仕込んだeaster egg(thisモジュールのこと。ソフトウェアでいうeaster eggとは隠しコマンドとか、隠しクレジットのようなもの)が誰かに見つかるまではしばらく時間がかかったそうだ。
Barry Warsaw氏が同記事を「That was all back in the day when the Python community had a sense of humor」という一文で締めくくっているように、この記事を読むと当時のPythonコミュニティがいかにユーモア溢れたものだったのかが感じられる。phython-2.2.1がリリースされたのは2002年4月10日で、それからどれくらい経ってこのthisモジュールが発見されたのか分からないが初めて発見した人は絶対ほっこりしたことだろう。
Note 1: import this
「The Zen of Python」はPythonハッカー、Tim Petersによって書かれた有名な文章でPython設計哲学を要約したようなものと言われている。 Barry Warsaw氏の記事によると起源はTim Peters氏による1999年6月4日のPython-listへのこの投稿のようだ。以下、Pythonインタラクティクモードでimport thisを実行し「The Zen of Python」を表示させた内容:
$ python Python 3.4.3 (default, Oct 14 2015, 20:28:29) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! >>>
Note 2: this.py
this.pyの中身。 意味不明なコードをROT13 (Note 3)で複合化することで「The Zen of Python」を出力している。
/usr/lib/python3.4/this.py
s = """Gur Mra bs Clguba, ol Gvz Crgref Ornhgvshy vf orggre guna htyl. Rkcyvpvg vf orggre guna vzcyvpvg. Fvzcyr vf orggre guna pbzcyrk. Pbzcyrk vf orggre guna pbzcyvpngrq. Syng vf orggre guna arfgrq. Fcnefr vf orggre guna qrafr. Ernqnovyvgl pbhagf. Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf. Nygubhtu cenpgvpnyvgl orngf chevgl. Reebef fubhyq arire cnff fvyragyl. Hayrff rkcyvpvgyl fvyraprq. Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff. Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg. Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu. Abj vf orggre guna arire. Nygubhtu arire vf bsgra orggre guna *evtug* abj. Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn. Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn. Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!""" d = {} for c in (65, 97): for i in range(26): d[chr(i+c)] = chr((i+13) % 26 + c) print "".join([d.get(c, c) for c in s])
Note 3: ROT13
ROT13は定められた置き換えマップにもとづいて文字を置き換えるだけの単純な暗号方式。次の変換マップに基づいて文字を変換するので例えばA→N、B→O、C→Pのように変換される。
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ↑↓ NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
ちなみにthis.pyではこの変換マップをモジュール中で生成しているがPython2系、3系ではROT13の実装は標準で組み込まれているので次のように直接decode関数に’rot13’を指定することでROT13で暗号化された文字列sを複合化することができる。
>>> this.s "Gur Mra bs Clguba, ol Gvz Crgref\n\nOrnhgvshy vf orggre guna htyl.\nRkcyvpvg vf orggre guna vzcyvpvg.\nFvzcyr vf orggre guna pbzcyrk.\nPbzcyrk vf orggre guna pbzcyvpngrq.\nSyng vf orggre guna arfgrq.\nFcnefr vf orggre guna qrafr.\nErnqnovyvgl pbhagf.\nFcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.\nNygubhtu cenpgvpnyvgl orngf chevgl.\nReebef fubhyq arire cnff fvyragyl.\nHayrff rkcyvpvgyl fvyraprq.\nVa gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.\nGurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.\nNygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.\nAbj vf orggre guna arire.\nNygubhtu arire vf bsgra orggre guna *evtug* abj.\nVs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.\nVs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.\nAnzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!" >>> this.s.decode('rot13') u"The Zen of Python, by Tim Peters\n\nBeautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!"
おわり
-
azuresshconfig has been dockerized
UPDATED 2017-02-15: changed docker run command example due to Issue#4
以前「azuresshconfigの紹介 – Azure上でのSSH生活を少しだけ快適にする」の投稿でazuresshconfigの紹介をさせていただいたが、ツールをリリースして以来、数少ない貴重な利用者様からインストールがコケるんだけど何とかしろというクレームをいただいていた。そこでインストールマニュアルを充実させようかとか、インストーラーをプラットフォーム別に充実させようかとか考えたものの、ここは流行りのコンテナ実行できるようしたほうがいいだろうということでDocker対応することにした。
今回の対応によりpipインストールや、プラットフォーム別にprerequisiteなランタイム、ヘッダファイル、ライブラリといった面倒なインストールが不要となり、Mac、Windows、Linux(Ubuntu、CentOS、その他distro)関係なくシンプルにdocker runコマンドでの実行が可能となった。
しかも超軽量LinuxディストリビューションであるAlpine Linuxの上にPythonランタイムとツールを載せているだけであるためサイズはたったの155MBとかなり軽め
$ docker images azuresshconfig REPOSITORY TAG IMAGE ID CREATED SIZE azuresshconfig latest 7488bef4343f 7 minutes ago 155 MB
実行例
$ docker run -v $HOME:/root --rm -it yoichikawasaki/azuresshconfig \ --output stdout --user yoichika --identityfile ~/.ssh/id_rsa > $HOME/.ssh/config
Dockerfileをダウンロードしてビルド・実行はこちら
$ curl https://raw.githubusercontent.com/yokawasa/azure-ssh-config/master/Dockerfile -o Dockerfile $ docker build -t azuresshconfig . $ docker run -v $HOME:/root --rm -it yoichikawasaki/azuresshconfig \ --output stdout --user yoichika --identityfile ~/.ssh/id_rsa > $HOME/.ssh/config
LINKS
Enjoy SSH life on Azure with dockerized azuresshconfig!
-
Logstash plugins for Microsoft Azure Services
Logstash is an open source, server-side data processing pipeline that ingests data from a multitude of sources simultaneously, transforms it, and then sends it to your favorite destinations. Here is a list of logstash plugins for Microsoft Azure Services.
Plugin Name Target Azure Services Note logstash-input-azureeventhub EventHub Logstash input plugin reads data from specified Azure Event Hubs logstash-input-azureblob Blob Storage Logstash input plugin that reads and parses data from Azure Storage Blobs logstash-input-azuretopic Service Bus Topic Logstash input plugin reads messages from Azure Service Bus Topics logstash-input-azuretopicthreadable Service Bus Topic Logstash input plugin reads messages from Azure Service Bus Topics using multiple threads logstash-output-applicationinsights Application Insights Logstash output plugin that store events to Application Insights logstash-input-azurewadtable Table Storage Logstash input plugin for Azure Diagnostics. Specifically pulling diagnostics data from Windows Azure Diagnostics tables logstash-input-azurewadeventhub EventHub Logstash input plugin reads Azure diagnostics data from specified Azure Event Hubs and parses the data for output logstash-input-azurewadtable Table Storage Logstash input plugin reads Azure diagnostics data from specified Azure Storage Table and parses the data for output logstash-output-documentdb Cosmos DB logstash output plugin that stores events to Azure Cosmos DB logstash-output-azuresearch Azure Search logstash output plugin that stores events to Azure Search logstash-output-azure_loganalytics Log Analytics logstash output plugin that stores events to Azure Log Analytics logstash-input-jdbc SQL Database, Azure Database for MySQL/PostgreSQL Input plugin to ingest data in any database with a JDBC interface into Logstash that support most of major RDBMS such as MySQL、PostgreSQL、OracleDB、Microsoft SQL, etc (as of Dec 29, 2016)
-
Detecting faces in Video contents using Azure Cognitive Services Face API
過去に本ブログでビデオコンテンツを切り口とした音声認識やOCR技術を利用したデモを紹介したが、ここではビデオコンテンツの中の人物出現箇所に連動して人物名を字幕で表示させるデモとその実装方法を紹介したい。人物識別にはAzureのCognitive ServicesのFace APIを使っていて、これで動画の中に出現する顔の検出を行い、予め登録している人物リストとのマッチングにより実現している。 Cognitive Serivcesとは視覚、音声、言語、知識などマイクロソフトがこれまで研究を通じて開発してきたさまざまな要素技術をAPIとして提供しているサービスのことで、最近巷で人工知能(AI)だとかインテリジェンスとかいうキーワードをよく耳にするのではないかと思うがAzure利用シナリオでそういったインテリジェンス(知能/知性)を兼ね備えたアプリを作る場合は間違いなく中核となるサービスの1つである。Face APIはその中でも顔の検出・識別や、顔にまつわる感情、特徴などメタデータ抽出に特化したAPIである。
主要テクノロジーと機能
下図は今回のデモ作成のために行っている処理フローと主要テクノロジーを表している。やっていることは大きく分けて3つ: (1) 動画コンテンツをAzure Media Encoder Standardを使ってフレームごとの静止画像の作成, (2) Cognitive ServicesのFace APIを使って1より得られた静止画像から顔の検出を行い予め登録している人物リストとマッチング(最も類似度が高いものを本人とみなす)して人物を識別, (3) 2で得られた各フレーム中の人物情報を時間順に並べて字幕(Closed Caption)用のデータファイルを生成。以下、各処理の詳細について説明する。
1. Azure Media Encoder Standardでフレームごとの静止画生成
残念ながらFace APIはビデオコンテンツから直接顔検出することができないため、一旦ビデオコンテンツから各フレームごとの静止画を生成してその静止画を対象に処理を行う必要がある。ここでは各フレームごとの静止画生成にAzure Media Encoder Standard(MES)を利用する。MESを使うことでエンコードタスクとしてビデオコンテンツに対して様々な処理を行うことができるのだが、MESにはそのエンコードタスクの1つとしてサムネイル生成のためのタスクが用意されており、今回はこのサムネール生成タスクを利用する。他のエンコードタスク同様にサムネイル生成タスクについてもプリセットと呼ばれるエンコードに必要な情報を記述した XML または JSON形式ファイルを用意する必要がある。今回は1秒フレームごとにJPEG形式の静止画(サムネイル)を生成するために次のようなプリセット(amsmp-thumbnail-config.json)を用意した。
{ "Version": 1.0, "Codecs": [ { "Start": "00:00:00", "Step": "00:00:01", "Type": "JpgImage", "JpgLayers": [ { "Quality": 90, "Type": "JpgLayer", "Width": 640, "Height": 360 } ] } ], "Outputs": [ { "FileName": "{Basename}_{Index}{Extension}", "Format": { "Type": "JpgFormat" } } ] }
MESによるサムネイル処理実行方法やプリセットの詳細については「Media Encoder Standard を使用した高度なエンコード」や同ページの「サムネイルを生成する」項を参照ください。尚、今回のサムネイル生成のためのエンコーディング処理は小生自作の「azure-media-processor-java」を利用してバッチ実行している。
2. Cognitive Services Face APIによる顔の検出と人物の識別
ここではCognitive ServicesのFace APIを使って1で得られたフレームごとの静止画像に対して顔検出を行い、予め登録している人物リスト(Face APIでいうところのPerson Group)と比較して最も類似度の高い人物(Face APIでいうところのPerson )をその本人として識別する。
2-1. 人物リスト(Person Group)の作成
人物リスト(Person Group)の作成で必要な作業とFace APIの利用インターフェースは次の通り:
- Create a Person Group APIを使って Person Groupを作成
- 上記で作成したPerson Groupの中にCreate a Person APIで人物ごとにPersonを作成する。作成されたPerson対してAdd a Person Face APIでその人物の顔画像を登録する。Face APIでは各Personに最大248枚の顔画像を登録が可能となっており、さまざまな種類の顔を登録することで機械学習によりその人物の顔識別の精度が向上するとされている。
- 上記でPerson Groupに対して登録されたPersonデータ(Personごとの顔データ)は最終的にTrain Person Group APIでトレーニングされることで、次の2-2で行う顔識別(Face Identify API)処理で利用可能なデータとなる。注意点として、いくらある人物の顔画像を登録したとしてもそれがトレーニングされない限り顔識別処理において有効にはならないため、新しく顔を登録した場合はトレーニング処理を忘れずに行ってください(この手のことは自動化しておいてください)。
2-2. 静止画像中の顔認識と人物識別
ここで行う処理の流れとFace APIの利用インターフェースは次の通り:
- Face Detect APIを使って静止画像中の顔を検出する。検出された顔ごとに固有のIDが得られる。尚、1枚の画像で複数の顔が検出された場合、最大64までは取得可能となっている(2016年12月現在)。
- 上記の顔検出で得られた顔IDを元にFace Identify APIを使って2-1で登録した人物リスト(Person Group)に対して人物検索を行い顔の類似度(0~1の数値)が高いもの順に一覧を取得することができる。ここでは最も類似度が高い人物をその顔の人物として決定する。
3. 字幕(Closed Caption)データファイルの生成
2で得られた各フレーム中の人物情報と各フレームの時間を元に字幕用のデータフォーマットであるWebVTTフォーマットファイルを生成する。以下、6秒~30秒までの字幕出力を期したWebVTTファイルのサンプルであるが、見ていただいてわかる通りフレームの時間(最小秒単位)とそこで得られた人物名をセットで記述するとても単純なフォーマットとなっている。
00:00:06.000 --> 00:00:07.000 Satya Nadella(0.73295)` 00:00:07.000 --> 00:00:08.000 Satya Nadella(0.6313) 00:00:27.000 --> 00:00:28.000 Bryan Roper(0.68094) 00:00:29.000 --> 00:00:30.000 Bryan Roper(0.54939)
各フレームの時間について、今回のビデオコンテンツのフレームは1秒ごとに取得しており、フレームごとの静止画像ファイルにはフレームの順番がPostfixとしてファイル名に含まれているため単純にファイル名からフレームの時間が特定できるようになっている(例, 10番目のファイル= videoassetname_000010.jpg)。もし今回のような機械的なルールがない場合はフレーム用画像ファイル名と時間のマッピングが必要となる。
ビデオコンテンツと字幕の再生は「ビデオコンテンツの音声認識デモ」でも紹介したようにHTML5のtrackタグエレメントによるビデオファイルの字幕表示機能使って人物名の字幕表示を実現している。本デモではHTML5に下記のようにビデオファイル(MP4)をVideoソースとしてtrackエレメントにWebVTTファイル(build2016keynote.vtt)を指定している。
<video id="Video1" controls autoplay width="600"> <source src="KEY01_VideoThumbnail.mp4" srclang="en" type="video/mp4"> <track id="trackJA" src="build2016keynote.vtt" kind="captions" srclang="ja" label="Person Name" default> </video>
デモデータ作成手順
GithubプロジェクトページVideoFramesFaceRecognition-Pythonの1. Preparationと2. Batch executionを実施いただければFace APIで識別した各フレームごとの人物名を元に字幕データ*.vttファイルが生成されデモページ表示のための準備は完了する。最後に表示用の静的ページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlの変更のみでいけるはず。
本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。
Azure Media Analytics Face Detectorを活用した処理の効率化
今回の人物識別ではビデオコンテンツの全てのフレームに対してFace APIを使って顔検出処理を行っているが、これでは顔出現フレームが少ないコンテンツの場合には無駄なFace APIリクエストが大量に発生してしまうため効率的な処理とは言えない。ということで、ここではAzure Media Face Detectorを活用して処理を効率化する方法を紹介したい。
Azure Media Face DetectorはAzure Media Servicesのメディアプロセッサ(MP)の1つで、ビデオコンテンツから顔の検出や感情の検出をすることができる。残念ながらAzure Media Face DetectorはFace APIのように顔の識別を行うことはできないものの、ビデオコンテンツから直接顔を検出することができる、即ちビデオコンテンツから直接顔が存在するフレームを特定することができる。よって、この機能を利用して一旦Azure Media Face Detectorで顔が検出されたフレームのみに絞り込んでからFace APIを使ってフレームの静止画像に対して顔検出・顔識別を行うことで無駄なFace APIリクエストを減らして処理の効率化を図ることができる。処理フローとしては次のようなイメージ。
おまけ: Video Summarization
デモページをみていただくとお分かりのように今回のデモでは3分のビデオコンテンツを題材としているが、元ネタはChannel9で公開されている計138分のBuild 2016のキーノートセッションである。このキーノートのセッションはデモコンテンツとしてはあまりに長かったのでこれをAzure Media Video Thumbnailsメディアプロセッサ(MP)を使って3分に要約している。Azure Media Video Thumbnailsはアルゴリズムベースで特徴シーンの検出とそれらを結合(サブクリップ)してビデオコンテンツを指定した長さに要約することができるMPで、現在Public Previewリリース中(2016年12月現在)。
参考までに、要約(3分:180秒)に使用したAzure Media Video Thumbnailsのタスクプリセットは以下の通り:
{ "version": "1.0", "options": { "outputAudio": "true", "maxMotionThumbnailDurationInSecs": "180", "fadeInFadeOut": "true" } }
END
-
Collecting events into Azure Functions and triggering your custom code using fluent-plugin-azurefunctions
In this article, I’d like to introduces a solution to collect events from various sources and send them into HTTP Trigger function in Azure Functions using fluent-plugin-azurefunctions. Triggers in Azure Functions are event responses used to trigger your custom code. HTTP Trigger functions allow you to respond to HTTP events sent from fluentd and cook them into whatever you want!
[note] Azure Functions is a (“serverless”) solution for easily running small pieces of code, or “functions,” in Azure. Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. fluent-plugin-azurefunctions is a fluentd output plugin that enables to collect events into Azure Functions.
Pre-requisites
- A basic understanding of fluentd - if you’re not familiar with fluentd, fluentd quickstart guide is good starting point
- Azure subscription - you need to have Azure subscription that grants you access to Microsoft Azure services, and under which you can create Azure Functions account. If you don’t have yet click here to create it
Setup: Azure Functions (HTTP Trigger Function)
Create a function (HTTP Trigger). First, you need to have an function app that hosts the execution of your functions in Azure if you don’t already have. Once you have an function app, you can create a function. Here are instructions:
A quick-start HTTP trigger function sample is included under examples/function-csharp in Github repository. You simply need to save the code (run.csx) and configuration files (function.json, project.json) in the same Azure function folder. Explaining a little bit about each of files, the function.json file defines the function bindings and other configuration settings. The runtime uses this file to determine the events to monitor and how to pass data into and return data from function execution. The project.json defines packages that the application depends. The run.csx is a core application file where you write your code to process Your jobs. Here is a sample run.csx:
using System.Net; using Newtonsoft.Json; public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) { log.Info("C# HTTP trigger function to process fluentd output request."); log.Info( string.Format("Dump request:\n {0}",req.ToString())); // parse query parameter string payload = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "payload", true) == 0) .Value; // Get request body dynamic data = await req.Content.ReadAsAsync<object>(); if (data.payload == null) { log.Info("Please pass a payload on the query string or in the request body"); return new HttpResponseMessage(HttpStatusCode.BadRequest); } // Process Your Jobs! dynamic r = JsonConvert.DeserializeObject<dynamic>((string)data.payload); if (r.key1!=null) log.Info(string.Format("key1={0}",r.key1)); if (r.key2!=null) log.Info(string.Format("key2={0}",r.key2)); if (r.key3!=null) log.Info(string.Format("key3={0}",r.key3)); if (r.mytime!=null) log.Info(string.Format("mytime={0}",r.mytime)); if (r.mytag!=null) log.Info(string.Format("mytag={0}",r.mytag)); return new HttpResponseMessage(HttpStatusCode.OK); }
Setup: Fluentd
First of all, install Fluentd. The following shows how to install Fluentd using Ruby gem packger but if you are not using Ruby Gem for the installation, please refer to this installation guide where you can find many other ways to install Fluentd on many platforms.
# install fluentd $ sudo gem install fluentd --no-ri --no-rdoc # create fluent.conf $ fluentd --setup
Also, install fluent-plugin-azurefunctions for fluentd aggregator to send collected event data into Azure Functions.
$ sudo gem install fluent-plugin-azurefunctions
Next, configure fluent.conf, a fluentd configuration file as follows. Please refer to this for fluent-plugin-azurefunctions configuration. The following is a sample configuration where the plugin writes only records that are specified by key_names in incoming event stream out to Azure Functions:
# This is used by event forwarding and the fluent-cat command <source> @type forward @id forward_input </source> # Send Data to Azure Functions <match azurefunctions.**> @type azurefunctions endpoint AZURE_FUNCTION_ENDPOINT # ex. https://<accountname>.azurewebsites.net/api/<functionname> function_key AZURE_FUNCTION_KEY # ex. aRVQ7Lj0vzDhY0JBYF8gpxYyEBxLwhO51JSC7X5dZFbTvROs7uNg== key_names key1,key2,key3 add_time_field true time_field_name mytime time_format %s localtime true add_tag_field true tag_field_name mytag </match>
[note] If key_names not specified above, all incoming records are posted to Azure Functions (See also this).
Finally, run fluentd with the fluent.conf that you configure above.
$ fluentd -c ./fluent.conf -vv &
TEST
Let’s check if test events will be sent to Azure Functions that triggers the HTTP function (let’s use the sample function included in Github repo this time). First, generate test events using fluent-cat like this:
echo ' { "key1":"value1", "key2":"value2", "key3":"value3"}' | fluent-cat azurefunctions.msg
As both add_time_field and add_tag_field are enabled, time and tag fields are added to the record that are selected by key_names before posting to Azure Functions, thus actual HTTP Post request body would be like this:
{ "payload": '{"key1":"value1", "key2":"value2", "key3":"value3", "mytime":"1480195100", "mytag":"azurefunctions.msg"}' }
If events are sent to the function successfully, a HTTP trigger function handles the events and the following logs can be seen in Azure Functions log stream:
2016-11-26T21:18:55.200 Function started (Id=5392e7ae-3b8e-4f65-9fc1-6ae529cdfe3a) 2016-11-26T21:18:55.200 C# HTTP trigger function to process fluentd output request. 2016-11-26T21:18:55.200 key1=value1 2016-11-26T21:18:55.200 key2=value2 2016-11-26T21:18:55.200 key3=value3 2016-11-26T21:18:55.200 mytime=1480195100 2016-11-26T21:18:55.200 mytag=azurefunctions.msg 2016-11-26T21:18:55.200 Function completed (Success, Id=5392e7ae-3b8e-4f65-9fc1-6ae529cdfe3a)
Advanced Senarios
1. Near Real-time processing
Function Apps can output messages to different means or data stores. For example, fluentd collects events generated from IoT devices and send them to Azure Function, and the the HTTP trigger function transforms the events and processes the data to store in a persistent storage or to pass them to different means. Here are some of options available at the time of writing:
- Store JSON documents on DocumentDB
- Send events to Event Hub
- Send messages to Azure Service Bus Queues
- Send messages to Azure Storage Queues
- Store blobs to Azure Blob Storage
- Push notifications to Notification Hub
- [Send SMS text messages via Twilio](https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-twilio)
- Send emails via SendGrid
2. Background jobs processing
If the jobs are expected to be large long running ones, it’s recommended that you refactor them into smaller function sets that work together and return fast responses. For example, you can pass the HTTP trigger payload into a queue to be processed by a queue trigger function. Or if the payload is too big to pass into the queue, you can store them onto Azure Blob storage at first, then pass only limited amount of the data into a queue just to trigger background workers to process the actual work. These approaches allow you to do the actual work asynchronously and return an immediate response.
LINKS
- fluent-plugin-azurefunctions
- Azure Functions Overview
- Azure functions Triggers and Bindings
- Azure Functions Best Practices
END
-
Video OCR using Azure Media & Cognitive
OCRとはOptical Character Recognitionの略で日本語にすると光学文字認識と訳されており、ざっくりと画像の中の文字をテキストに変換する技術のことを指す。テキストに変換されるということは勘が鋭い皆さんはお気づきだと思うが、テキストの全文検索であったり、テキストから音声への変換、さらには機械翻訳を使って多言語への変換といった展開が考えられる。そんな可能性を秘めたOCRであるが、ここではそのOCRの技術を使ってビデオファイルから抽出したテキストデータを元にビデオに字幕表示したり、動画中に表示される文字を全文検索をするデモを紹介したい。内容的には「Azure Media & Cognitiveデモ:Speech-To-Text」で紹介したデモのOCR版といったところ。
主要テクノロジーと機能
Azure Media OCRメディアプロセッサによるテキスト抽出
このデモではAzure Media OCRメディアプロセッサー(MP)を使用してビデオファイル内のテキストコンテンツを検出してテキストファイルを生成している。OCRメディアプロセッサーは入力パラメータによりビデオ解析の挙動を調整することができる。主なパラメータとしては検索対象テキストの言語(日本語もサポート)、テキストの向き、サンプリングレート、ビデオフレーム内のテキスト検出対象のリージョンがあるが、本デモでの入力パラメータ(Video-OCR-Search-Python/src/ocr-detectregion.json)は以下の通り検索対象言語は日本語、1秒おきのサンプリングレート、テキスト検出対象のリージョンからビデオフレーム内の上部1/4を省く設定(検出対象をフレームトップから85 pixel以下を対象)にしている。
{ "Version":"1.0", "Options": { "Language":"Japanese", "TimeInterval":"00:00:01.000", "DetectRegions": [ {"Left":"0","Top":"85","Width":"1280","Height":"635"} ] } }
そして、Azure Media OCRメディアプロセッサはビデオで検出された文字を下記のような表示時間に基づいてセグメント化された形で結果出力する。結果ファイルの完全版はこちら(azuresubs.json)を参照ください。
{ "fragments": [ { "start": 0 "interval": 319319, "duration": 319319, "events": [ [ { "language": "Japanese", "text": "Azure の 契 約 内 容 を 変 更 す る Microsoft Azure" } ] ] }, { /* fragment1 */ }, { /* fragment2 */ }, ... { /* fragmentN */ } ], "version": 1, "framerate": 29.97, "height": 720, "width": 1280, "offset": 0, "timescale": 30000 }
入力パラメータと出力形式共に詳細はこちらのドキュメントを参照いただくとしてAzure Media OCRメディアプロセッサ利用の注意点として次の2つがある:
- 「Azure Media OCR Simplified Output」の記事でアナウンスされている通り2016年9月ごろからデフォルトの出力形式が上記ドキュメントページにある詳細形式からシンプル形式に変わっている
- Azure Media OCRメディアプロセッサー(MP)は現時点(2016年11月7日)では正式リリースではなくプレビューリリース
字幕(Closed Caption)データフォーマットへの変換
まず上記Azure Media OCRメディアプロセッサー(MP)から出力されたJSONファイルの内容を元に字幕用のデータフォーマットであるWebVTTフォーマットファイルを生成している。そして「Azure Media & Cognitiveデモ:Speech-To-Text」でも紹介したようにHTML5のtrackタグエレメントによるビデオファイルの字幕表示機能使ってOCRの内容の字幕表示を実現している。本デモではHTML5に下記のように動画(TransferanAzuresubscriptionJP.mp4)をVideoソースとしてtrackエレメントにWebVTTファイル(azuresubs.vtt)を指定している。
<video id="Video1" controls autoplay width="600"> <source src="TransferanAzuresubscriptionJP.mp4" srclang="en" type="video/mp4"> <track id="trackJA" src="azuresubs.vtt" kind="captions" srclang="ja" label="OCR Subtitle" default> </video>
Azure Searchによる全文検索
デモページ上部にある検索窓にキーワードを入力してGoボタンを押すとビデオコンテンツからOCR抽出されたテキストを元に生成された字幕データを全文検索してキーワードにマッチしたテキストとその表示時間に絞り込むことができる。仕組みは「Azure Media & Cognitiveデモ:Speech-To-Text」と全く同じで、Azure Searchを使用して字幕データを解析して字幕表示時間とその対応テキストを1ドキュメントレコードとしてAzure Searchにインジェストしてその生成されたインデックスに対してキーワードを元に全文検索することで実現している。検索用のインデックススキーマもまったくおなじで次のように字幕表示時間とその対応テキストをレコード単位となるように定義している。
{ "name": "ocr", "fields": [ { "name":"id", "type":"Edm.String", "key": true, "searchable": false, "filterable":false, "facetable":false }, { "name":"contentid", "type":"Edm.String","searchable": false, "filterable":true, "facetable":false }, { "name":"beginsec", "type":"Edm.Int32", "searchable": false, "filterable":false, "sortable":true, "facetable":false }, { "name":"begin", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false }, { "name":"end", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false }, { "name":"caption", "type":"Edm.String", "searchable": true, "filterable":false, "sortable":false, "facetable":false, "analyzer":"ja.microsoft" } ] }
デモデータ作成手順
GithubプロジェクトページVideo-OCR-Search-Pythonの1. Preparationと2. Batch executionを実施いただければOCR抽出されたテキストを元に字幕データ*.vttファイルが生成され、そのテキストがAzure Searchに格納されてデモページ表示のための準備は完了する。最後に表示用のページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlとsearch.jsの変更のみでいけるはず。
本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。
Enjoy Video OCR demo!
-
Speech-To-Text with Azure Media & Cognitive Services
ビデオコンテンツを音声認識エンジンでテキスト化してそれを元にスピーチ検索するデモコンテンツを紹介したい。これは過去にde:code2016というマイクロソフトの開発者向けイベントで行ったブレイクアウトセッション「DEV-18: Azure Search Deep Dive」にて紹介したビデオコンテンツのスピーチ検索デモを簡略化して再利用しやすいものにしたものである。
主要テクノロジーと機能
Azure Media Indexer 2 Previewによる音声からテキスト抽出
このデモではAzure Media Indexer 2 Preview メディア プロセッサー (MP)を使用してビデオコンテンツからテキストを抽出している。このAzure Media Indexer 2 Previewは自然言語処理(NLP)や音声認識エンジンを駆使してビデオコンテンツより字幕用データ(時間やテキスト)や検索可能にするためのメタデータを抽出することができる。Indexer 2という名前の通り前のバージョンであるAzure Media Indexerが存在するが、これと比較すると、Azure Media Indexer 2 Previewは、インデックス作成が高速化され、より多くの言語をサポートしていることが特徴である。2016年11月6日時点で英語、スペイン語、フランス語、ドイツ語、イタリア語、中国語、ポルトガル語、アラビア語などがサポートされている(残念ながら日本語はまだ未サポート)。
下イメージはAzure Media Indexer 2 (Preview)で生成されるTTMLとWebVTTという代表的な字幕データフォーマット。
HTML5と字幕(Closed Caption)
HTML5にはtrackタグエレメントを使ってビデオファイルに字幕を表示する機能が標準的に実装されている。本デモではHTML5に下記のように動画(Python_and_node.js_on_Visual_Studio.mp4)をVideoソースとしてtrackエレメントに字幕WebVttファイル(build2016breakout.vtt)を指定している。
<video id="Video1" controls autoplay width="600"> <source src="Python_and_node.js_on_Visual_Studio.mp4" srclang="en" type="video/mp4"> <track id="trackJA" src="build2016breakout.vtt" kind="captions" srclang="ja" label="Closed Captions" default> </video>
Azure Searchによる全文検索
デモページ上部にある検索窓にキーワードを入力してGoボタンを押すとビデオコンテンツの字幕データを全文検索してキーワードにマッチしたテキストとその表示時間に絞り込むことができる。ここでは全文検索エンジンにAzure Searchを使用し、Azure Media Indexer 2 (Preview)より抽出された字幕データを解析して字幕表示時間とその対応テキストを1ドキュメントレコードとしてAzure Searchにインジェストしてその生成されたインデックスに対してキーワードを元に全文検索することで実現している。字幕データ検索用のインデックススキーマは次のように字幕表示時間とその対応テキストをレコード単位となるように定義している。
{ "name": "stt", "fields": [ { "name":"id", "type":"Edm.String", "key": true, "searchable": false, "filterable":false, "facetable":false }, { "name":"contentid", "type":"Edm.String","searchable": false, "filterable":true, "facetable":false }, { "name":"beginsec", "type":"Edm.Int32", "searchable": false, "filterable":false, "sortable":true, "facetable":false }, { "name":"begin", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false }, { "name":"end", "type":"Edm.String", "searchable": false, "filterable":false, "sortable":false, "facetable":false }, { "name":"caption", "type":"Edm.String", "searchable": true, "filterable":false, "sortable":false, "facetable":false, "analyzer":"en.microsoft" } ] }
デモデータ作成手順
GithubプロジェクトページVideo-STT-Search-Pythonの1. Preparationと2. Batch executionを実施いただければ字幕データ*.vttファイルが生成され、そのテキストがAzure Searchに格納されてデモページ表示のための準備は完了する。最後に表示用のページを生成すれば完了。本デモの表示用ページデータはこちらで、基本的にindex.htmlとsearch.jsの変更のみでいけるはず。
本デモコンテンツについて何か問題を発見した場合はこちらのGithub IssueページにIssueとして登録いただけると幸いである。
Enjoy Video Speech-to-text demo!
-
Making SSH lives in Azure easier with azuresshconfig
UPDATED 2016-10-31: paramsオプション + Bash Completion追加
みんな大好きSSHとAzureのお話し。物理サーバ、EC2/仮想マシン、コンテナなどなんでもよいがその上にLinuxサーバをたてたらまずやることの1つにSSHログインのためにそのIPアドレス調べて
~/.ssh/config
にそのエントリーを追加してやることがあるんじゃないかと思います。この作業、エントリー数が少なければ大したことはないものの、追加対象のホストが大量にある場合はかなり面倒な作業になってきます。さらにDHCPなどでアドレスを動的に取得するような設定であればサーバの上げ下げのたびにIPアドレスが変わってくるので~/.ssh/config
の更新が必要になってきて、どうしようもなく面倒になってきます。こういった単純でどうしようもなくつまらない作業は自動化したいですよね? ここではそんな皆さんのためにazuresshconfigというツールを紹介させていただきます。これは皆さんのAzureサブスクリプション下に作られた仮想マシン一覧(ARMに限る)の情報を取得して各仮想マシンごとのエントリー情報(マシン名とIPアドレス)を~/.ssh/configに追加・更新してくれるツール。新規に仮想マシンを追加した際や、仮想マシンのIPアドレスが追加した際には
azuresshconfig
を実行してあげることで~/.ssh/config
が最新のエントリー情報でアップデートされ、各マシンにマシン名でSSHログインできるようになります。ちなみに、
~/.ssh/config
とは何ですか?という人はQiitaの記事「~/.ssh/configについて」がとても分かりやすく書かれているので参考になるかと。インストール
Pythonパッケージ管理ツール
pip
を使ってazuresshconfig
をインストールしてください。インストール時に何かエラーが発生した場合は、こちらのページを参照いただき特に該当する事象がないか確認ください。$ pip install azuresshconfig
設定ファイルの編集(サービスプリンシパル)
$ vi $HOME/.azure/azuresshconfig.json { "subscription_id": "", "client_id": "", "client_scret": "", "tenant_id": "" }
サービスプリンシパル
を作る必要があります。サービスプリンシパル
の作り方が分からない人、とってもよいドキュメントがあります。こちらを参照ください:「Use Azure CLI to create a service principal to access resources」使い方
azuresshconfig --help usage: azuresshconfig.py [-h] [--version] [--init] [--profile PROFILE] [--user USER] [--identityfile IDENTITYFILE] [--private] [--resourcegroups RESOURCEGROUPS] [--params PARAMS] This program generates SSH config from Azure ARM VM inventry in subscription optional arguments: -h, --help show this help message and exit --version show program's version number and exit --init Create template client profile at $HOME/.azure/azuresshconfig.json only if there is no existing one --profile PROFILE Specify azure client profile file to use ($HOME/.azure/azuresshconfig.json by default) --user USER SSH username to use for all hosts --identityfile IDENTITYFILE SSH identity file to use for all hosts --private Use private IP addresses (Public IP is used by default) --resourcegroups RESOURCEGROUPS A comma-separated list of resource group to be considered for ssh-config generation (all resource groups by default) --params PARAMS Any ssh-config params you want to add with query- string format: key1=value1&key2=value2&...
実行する
1. パラメータ指定なしで実行
$ azuresshconfig
~/.ssh/config
には下記のように### AZURE-SSH-CONFIG BEGIN ### ~ ### AZURE-SSH-CONFIG END ###
のブロック内にマシン名とそのIPアドレス(デフォルト:パブリック)のエントリー一覧が追加・更新されます。$ cat ~/.ssh/config ### AZURE-SSH-CONFIG BEGIN ### Host myvm1 HostName 40.74.124.30 Host myvm2 HostName 40.74.116.134 .... ### AZURE-SSH-CONFIG END ###
2. SSHユーザと鍵指定
$ azuresshconfig --user yoichika --identityfile ~/.ssh/id_rsa
~/.ssh/config
には各エントリーにIPアドレスに加えてユーザ名と鍵のパス情報が追加されます。$ cat ~/.ssh/config ### AZURE-SSH-CONFIG BEGIN ### Host myvm1 HostName 40.74.124.30 IdentityFile /home/yoichika/.ssh/id_rsa User yoichika Host myvm2 HostName 40.74.116.134 IdentityFile /home/yoichika/.ssh/id_rsa User yoichika .... ### AZURE-SSH-CONFIG END ###
3. プライベートIPを指定
$ azuresshconfig --user yoichika --identityfile ~/.ssh/id_rsa --private
private
オプションを付けて実行することで~/.ssh/config
の各エントリーにはデフォルトのパブリックIPアドレスではなくてプライベートIPアドレスが追加されます。4. リソースグループで絞る
$ azuresshconfig --user yoichika --identityfile ~/.ssh/id_rsa --resourcegroups mygroup1,mygroup2
resourcegroups
オプションを指定することで指定されたリソースグループに所属する仮想マシンのエントリーのみが~/.ssh/config
に追加されます。5. 追加ssh-configパラメータの指定
$ azuresshconfig.py --user yoichika \ --identityfile ~/.ssh/id_rsa \ --params "Port=2222&Protocol=2&UserKnownHostsFile=~/.ssh/known_hosts&ForwardAgent=yes"
params
オプションを指定することでその他指定可能なssh-config
パラメータを追加することができます。上記のようにparams
にssh-config
のPort、Protocol、UserKnownHostsFile、ForwardAgent
キーと値をセットすることで次のように出力されるssh-config
に指定したキーと値がセットされます。$ cat ~/.ssh/config ### AZURE-SSH-CONFIG BEGIN ### Host myvm1 HostName 40.74.124.30 IdentityFile ~/.ssh/id_rsa User yoichika Port 2222 Protocol 2 UserKnownHostsFile ~/.ssh/known_hosts ForwardAgent yes Host myvm2 HostName 40.74.116.134 IdentityFile /home/yoichika/.ssh/id_rsa User yoichika Port 2222 Protocol 2 UserKnownHostsFile ~/.ssh/known_hosts ForwardAgent yes .... ### AZURE-SSH-CONFIG END ###
Shell Completion
Bashでの補完
次のようにbash/azuresshconfig_completion.bashをbash起動時に読み込ませてあげることで
azuresshconfig
のパラメータ補完ができるようになります.# copy this under either of following directories $ cp azuresshconfig_completion.bash (/etc/bash_completion.d | /usr/local/etc/bash_completion.d | ~/bash_completion.d)` # or append 'source /path/to/azuresshconfig_completion.bash' to .bashrc like this $ echo 'source /path/to/azuresshconfig_completion.bash' >> .bashrc
次のようにtabでazuresshconfigのパラメータ補完を行います。
$ azuresshconfig -[tab] -h --identityfile --params --profile --user --help --init --private --resourcegroups $ azuresshconfig --i[tab] --identityfile --init $ azuresshconfig --p[tab] --params --private --profile $ azuresshconfig --user [tab] $ azuresshconfig --user <ssh_user> $ azuresshconfig --user <ssh_user> --identityfile [tab] $ azuresshconfig --user <ssh_user> --identityfile <ssh_identity_file>
その他
インストール時のエラーや実行時のエラーについてはこちらに見つけ次第事象とその対応方法を追加しています。 https://github.com/yokawasa/azure-ssh-config/blob/master/Issues.md
もしバグを見つけたり、追加機能のリクエストがある場合にこちらにIssue追加ください。頑張って時間をみつけて対応します。 https://github.com/yokawasa/azure-ssh-config/issues
LINKS
- https://github.com/yokawasa/azure-ssh-config
- https://pypi.python.org/pypi/azuresshconfig/
- Use Azure CLI to create a service principal to access resources
azuresshconfig makes your SSH life on Azure easy!
-
embulk plugins for Microsoft Azure Services
Here is a list of embulk plugins that you can leverage to transfer your data between Microsoft Azure Services and various other databases/storages/cloud services.
Plugin Name Target Azure Services Note embulk-output-azure_blob_storage Blob Storage Embulk output plugin that stores files onto Microsoft Azure Blob Storage embulk-input-azure_blob_storage Blob Storage Embulk input plugin that reads files stored on Microsoft Azure Blob Storage embulk-output-sqlserver SQL Databases, SQL DWH Embulk output plugin that Inserts or updates records to SQL server type of services like SQL DB/SQL DWH embulk-input-sqlserver SQL Databases, SQL DWH Embulk input plugin that selects records from SQL type of services like SQL DB/SQL DWH embulk-output-documentdb Comos DB Embulk output plugin that dumps records to Azure Cosmos DB embulk-output-azuresearch Azure Search Embulk output plugin that dumps records to Azure Search (as of Aug 30, 2016)
For embulk, check this site: https://github.com/embulk/embulk