This blog primarily talks about Tiller server, especially creating service account and cluster role binding for it.
还有一种解决办法是Tillerless, 将Tiller server 运行在本地的container中,见我的 <<Helm Quick Start>>
Zen uses Helm to install in ICP4D cluster. Helm is a tool for managing Kubernetes charts. Charts are packages of pre-configured Kubernetes resources. Think of Helm like apt(deb), yum(rpm), homebrew for Kubernetes.
Download the Latest release from Helm Release. For example in Linux, we use:
1
Linux amd64 (checksum / 9f50e69cf5cfa7268b28686728ad0227507a169e52bf59c99ada872ddd9679f0)
Helm needs to be put in the control node that already configured with kubectl.
Untar the file and you can move helm binary to one of the exectuable path, such as /usr/local/bin:
1 2
# which helm /usr/local/bin/helm
Deploy Tiller Server
Helm client needs to talk to Tiller server, which will be deploied in the K8s cluster.
Most cloud providers enable a feature called Role-Based Access Control - RBAC for short. If your cloud provider enables this feature, you will need to create a service account for Tiller with the right roles and permissions to access resources.
From here, you need to create a cluster role binding which specifies a role and a service account name that have been set up in advance rbac-config.yaml:
If you forget to create service account and cluster role binding before you initiate Helm, no worries, create rbac-config.yaml objects and patch it by:
There are by default 7 SCCs in OpenShift, but that may not satisfy the demands and it’s better to create a new dedicated one to use for non-root deployment.
Let’s see how to grant a regular user sudo privilege, this is summaried from process to use regular user instead of root. Use of sudo does not require access to the superuser’s password. If Authenticating, using sudo requires the user’s own password.
Say, there is a regular user named guest, the simplest way is to edit sudoers file solely, run as root user:
1
visudo
Append this line after root user field
1 2 3
# root ALL=(ALL) ALL # 如果需要仅仅开放某些命令,这里可以进行调整 guest ALL=(ALL) ALL
Then user guest can run sudo free.
Another way is adding guest user to wheel group then give this special group password-less sudo privilege.
why uses wheel? Because sometimes I also need grant su password-less to the user, wheel group is easy for both. See my blog <<Linux PAM Module Configuration>>
Run as root user, add guest to wheel group:
1
usermod -a -G wheel guest
Then edit sudoers file
1
visudo
Comment and uncomment like this:
1 2 3 4 5
## Allows people in group wheel to run all commands #%wheel ALL=(ALL) ALL
## Same thing without a password %wheel ALL=(ALL) NOPASSWD: ALL
I was previously working on a separate branch branch-tmp, now I want to merge some files in that branch into my main personal branch chengdol_master, and finally create a pull request to merge int master.
Notice that in my case, the target files in branch-tmp are completely applicable for chengdol_master, so I just want to overwrite corresponding files in chengdol_master. If we need to pick some changes and leave others in the file, do an interactive merge, run this from chengdol_master:
1
git checkout --patch brach-tmp <relative path to target file>
First check if you have origin/branch-tmp locally
1
git branch -r | grep branch-tmp
If not, you need to fetch it alone or fetch all origin branches:
1 2
git fetch origin branch-tmp git fetch origin
Then go to your target branch chengdol_master, use git checkout command to do the job:
1
git checkout origin/branch-tmp <relative path to target file>
then the merged files from branch-tmp are in staging phase, you can directly commit or unstage them in the chengdol_master branch, then push and handle the pull request.
// get min value >= x // 返回的都是整数,但是是double type Math.ceil(double x) // get max value <= x // 返回的都是整数,但是是double type Math.floor(double x) // log e of x Math.log(double x) // calculate log2 Math.log(x) / Math.log(2)
Complete binary tree number of nodes: 2^height - 1 (height start from 1)
For segment tree, number of nodes:
1 2 3 4
// n is the length of array inth= (int)Math.ceil(Math.log(n) / Math.log(2)); intmaxSTSize=2 * (int)Math.pow(2, h) - 1; int[] st
Or you can define class Node to build segment tree.
List
LinkedList is doubly-linked!
change array to list
1
List<Integer> list = Arrays.<Integer>asList(1, 2, 3, ...);
but this is fixed size list backed by array, you can create a new one:
1
List<Integer> list = newArrayList<Integer>(Arrays.<Integer>asList(1,2,3, ...));
use slow-fast pointer to find middle of linkedlist or find cycle
1 2 3 4 5 6
ListNodeslow= head, fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } // when loop break, slow is in middle
Stringstr=newString("123"); Stringstr="123"; // convert number 123456 to string "123" Stringstr= String.valueOf(123456); str.length(); // use + to concatenate str1 + str2 // string compare str1.compareTo(str2);
when do replace
1 2 3 4
Stringstr="a.b.c.d"; str.replace(".", ""); // get "abcd" // don't use str.replace('.',''), cannot be empty char // there is no regex, just CharSequence type
if just want to create a string using other type:
1
"" + other type
caution:
1 2 3 4 5 6
Stringa="1.2.3."; // a.split("\\.") will get length of 3, it will ignore last '.' Stringa=".1.2.3"; // a.split("\\.") will get length of 4, it will not ignore first '.' Stringb="1..2.3"; // b.split("\\.") will get length of 4, it will not ignore consecutive '.'
Notice the parameters format
1 2 3 4 5 6
indexOf(int ch, int startIndex) split(String reg)
// returns the index within this string of // the last occurrence of the specified character. int lastIndexOf(int ch)
StringBuilder
1 2 3 4 5 6 7 8 9
StringBuildersb=newStringBuilder(String); sb.append(x); // insert in head sb.insert(0, x); sb.toString(); // return stringbuilder sb.reverse(); // stringbuilder does not implement equals method!! sb.equals(another stringbuilder object); // wrong!!
more methods:
1 2 3 4 5 6 7
// return String // 这里只有一个参数的时候是start index! substring(int startidx) // [start end) substring(int startidx, int endidx) append(lot of types) setLength(int len)
Character
1 2 3 4 5 6 7 8
// return Character Character.valueOf(char) //return char c.charValue()
// actually the convert is auto like int and Integer! charc1=newCharacter('a'); Characterc1='b';
char compare in if use ==
if use ± with char, such as ch - 'a', don’t forget (char)(ch)
List<Integer> list = Arrays.stream(ints).boxed().collect(Collectors.toList());
这个是Java stream的知识点
Array
1 2 3 4 5 6 7
// one dimension int[] arr = newint[]{1,2,3}; int[] arr = newint[4]; // default value is 0 // two dimensions int[][] arr = newint[3][4]; // 3 rows 4 columns int[][] arr = newint[3][]; // still ok, you can init one dimension array later int[][] arr = newint[][]{{1,2,3}, {4,5}, {6,7,8,9}}; // each one dimension array can have different length!
Let’s see char array
1
char[] arr = str.toCharArray();
Use sort static method, if you want to use comparator, see my lambda section
1 2 3
Arrays.sort(E[] e); // also for collections Collections.sort(List<xx> l);
// nums[0] swap with element in range [0, n) // nums[1] swap with element in range [1, n) // nums[2] swap with element in range [2, n) publicstaticint[] shuffle(int[] nums) { for (inti=0; i < nums.length; i++) { intj= i + rand.nextInt(nums.length - i); // swap inttmp= nums[i]; nums[i] = nums[j]; nums[j] = tmp; } return nums; }
Set
TreeSet operation time complexity, from java TreeSet doc:
This implementation provides guaranteed log(n) time cost for the basic operations (add, remove and contains).
Map
1
import java.util.*;
HashMap<>() not thread safe
HashTable<>(), thread safe but ConcurrentHash…
map.containsKey() // also has contains value method! map.containsValue() // return set map.keySet() map.entrySet() // return collection map.values()
1 2 3 4 5 6
// provide value for new key which is absent map.put(key, map.getOrDefault(key, 0) + 1); // if value is a collection object can use: map.computeIfAbsent(key, k -> newArrayList<Stone>()).add(newStone(x,y)); // remove current key if it's value is val map.remove(key, val)
Treemap/TreeSet (sorted map) perform all operation based on it’s default/custom comparator! if two key are equal in comparator, should be treated as equal in equals() method! 但如果没有一致,还是按照comparator去做. treemap/treeset.remove(object) 用的是comparator去比较相等!!
import java.util.Random; Randomrand=newRandom(); intrandomNum= rand.nextInt((max - min) + 1) + min; // simply can use this: // return double, need to force convert to int maybe Math.random(): [0.00,1.00)
Lambda Expression
for comparator and comparable, let’s see how to wirte it, this post
int[][] arr = {{5,1}, {2,3}}; // sort by the first element of one dimenstional array Arrays.sort(arr, (int[] a, int[]b) -> a[0] - b[0]); System.out.println("result= " + Arrays.deepToString(arr));
I just recently interviewed with 16 different companies in the silicon valley (including FAANG except Netflix) for senior software engineering positions. Here’s my opinion, based on my experience:
Some interviewers will expect you to know why Deque is better than Stack.
Showing mastery of at least one programming language (in this case, Java) can, at worst, score you extra points in the interview, and at best get you the job and even help you get higher compensation or leveling. Getting the optimal solution is the basic requirement to pass an interview. Additionally, you are being benchmarked against other candidates being asked exactly the same question. Lastly, for those targeting senior level positions, the interviewer will also evaluate your seniority. This is one case where I think most interviewers will expect to see that you’ve mastered the Java programming language (if you chose to use it in your interview).
Here are a few reasons why Deque is better than Stack:
Object oriented design - Inheritance, abstraction, classes and interfaces: Stack is a class, Deque is an interface. Only one class can be extended, whereas any number of interfaces can be implemented by a single class in Java (multiple inheritance of type). Using the Deque interface removes the dependency on the concrete Stack class and its ancestors and gives you more flexibility, e.g. the freedom to extend a different class or swap out different implementations of Deque (like LinkedList, ArrayDeque).
Inconsistency: Stack extends the Vector class, which allows you to access element by index. This is inconsistent with what a Stack should actually do, which is why the Deque interface is preferred (it does not allow such operations)–its allowed operations are consistent with what a FIFO or LIFO data structure should allow.
Performance: The Vector class that Stack extends is basically the “thread-safe” version of an ArrayList. The synchronizations can potentially cause a significant performance hit to your application. Also, extending other classes with unneeded functionality (as mentioned in #2) bloat your objects, potentially costing a lot of extra memory and performance overhead.
Tries
string symbol table: specialized to string key. Faster than hashing, flexible then BST
recall the structure of tries, very simple! put value in last node (character).
put and search method for tries can be recursion implementations.
一般都用的这个。
3-way tries: 这里注意,当前char的值和node char比较,less then go left, larger then go right, then compare, if not match, miss hit. Using recursion to do put and search operation. TST is as fast as hashing (for string key) and space efficient. support in-order traverse (obey BST rule)
constant O(1) logarithmic O(logn) linear O(n) quasilinear O(nlogn) quadratic O(n^2), n to the power of 2 cubic O(n^3), n to the power of 3 polynomial O(n^x + n^y + ..) exponential O(2^n) factorial O(n!)
Tilde notation: ignore lower order terms, negligible
best case, lower bound
worst case, upper bound, Big O does this
average case, cost for random input, expected cost
when upper bound equals lower bound, we get optimal algorithms
Average O(n), worst case O(n^2), need to shuffle.
if quick select Kth element, then in the range [0, K] is guarantee the K smallest elemets in unsorted array.
how to decide the condition?
lo < hi or lo <= hi?
hi = mid - 1 or hi = mid?
lo = mid + 1 or lo = mid?
when target exists, use
1
while (lo <= hi)
because it will finally concentrate. lo == hi will be the result:
hi = mid - 1 or hi = mid?
or
lo = mid + 1 or lo = mid?
does not matter.
对于可能不存在的也用lo <= hi,但要保证hi = mid - 1 和 lo = mid + 1
You use while (start <= end) if you are returning the match from inside the loop.
You use while (start < end) if you want to exit out of the loop first, and then use the result of start or end to return the match.
Backtracking
Backtracking is an algorithmic-technique for solving problems recursively by trying to build a solution incrementally, one piece at a time, abandons those solutions that fail to satisfy the constraints of the problem at any point of time.
for example:
SudoKo
N Queens problem, smart at process diagonal row-col and row + col. think recursion as a tree, back and forth.
leetcode summary backtracking about Subsets, Permutations, and Combination Sum
Others
x^y how to describe: x to the power of y
x^2: x squard
x^3: x cubed
Find rectangle
p1[x,y], p2[x,y]
if p1 and p2 are diagonal, check if other 2 points exist, can use hashmap or hashset
Toggle 1 and 0
use xor 1 to toggle 1 and 0
1 2 3
inta=1 a ^= 1; // a is 0 a ^= 1; // a is 1
calculate power of 2:
1 2 3
Math.pow(2, n); // slow // or can use shift 1 << n // fast
Union Find
for quick find, all sites in a component must have the same value in id[], directly check id[p] == id[q]
for quick union, set the root of pool p to the root of q
then improve quick union, compress the path when seach the root:
1 2 3 4 5 6 7 8 9
privateintfind(int[] uf, int i) { while (uf[i] != i) { // path compression uf[i] = uf[uf[i]]; i = uf[i]; } }
sort
in-place:
bobble sort stable
selection sort not stable
insertion sort stable
quick sort not stable
heap sort not stable
need space:
merge sort stable
a connected component is a max pool of connected vertices
answer the question: is v and w connected in contact time.
DFS? yes, run DFS for each unvisited vertex, verteice in same connected component has the same id (this can represent component number!), so, check vertex id will get result.
Directed graph
also called digraph
outdegree, indegree
directed cycle
DAG: directed acyclic graph
Unweighted
without weight on edge, the same for DFS and BFS
we use adjacency list the same as undirected graph
1
List<Integer>[] adj;
topological sorting
for example, precedence scheduling
at least one vertex has 0 indegree and should be directed acyclic graph (DAG)
non-negative weightSPT: shortest path tree exist in graph from the source vertex
remember:
Use minium priority queue, to choose the next vertex cloest to the source vertex!
Then update the path accordingly if it’s shorter than before (如何实现这个degrade呢?)
implementation
I have worked on Kubernetes and OpenShift for several months, both are good container management and schedule tools, they have many overlaps and the kubectl commands are compitable in OpenShift, so what the exactly differences between them are?
OpenShift is a family of containerization software developed by Red Hat. Its flagship product is the OpenShift Container Platform, an on-premises platform as a service built around Docker containers orchestrated and managed by Kubernetes on a foundation of Red Hat Enterprise Linux.
Kubernetes is an integral part of OpenShift with more features built around it.
OpenShift has more strict security policies than default Kubernetes, most of container images available on Docker Hub or we have built before won’t run on OpenShift, because it forbids to run a container as root. we need to relax this strict to give the workspace higher privileges to run container as root, or update our image to
Sometimes if the local working branch messes up but you want to sync up with your remote branch, for example origin master, first remove all untracked files:
1 2 3 4 5
# -d: remove untracked dirs # -f: force git clean -df # -x: remove ignored files as well git clean -dfx
you can have a dry-run first to see what files will be removed
1 2
# -n: dry run git clean -dfn
Check the commit logs in current branch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# verbose # -n: commit number git log -n 10
# oneline and color # color: show color git log --oneline --color -n 10
# -p: show diff for each commit git log -p --oneline --color -n 10
# show branch relationship # --graph: show ascii graph git log --graph --oneline --color -n 10
Then properly select one good commit that also appears in remote master branch, run
1
git reset --hard <good commit hash>
All the commits later than the good commit hash will be removed, then you can just run the command below to sync up remote master branch.
1
git pull origin master
Note that it’s safe to do git reset here because only I use this branch and I want to clean
Sometimes I see people use:
1 2 3 4
# reset to current commit, discard all uncommitted changes git reset --hard HEAD # HEAD~1: move to the commit right before HEAD git reset --hard HEAD~1
HEAD points to your current commit, check by:
1 2
# get HEAD short hash git rev-parse --short HEAD
so all that git reset --hard HEAD will do is to throw away any uncommitted changes you have and point to your latest commit.